remove lfds v6, lfds v7 for flexran only
This commit is contained in:
@@ -1103,8 +1103,6 @@ include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/S1AP")
|
||||
include_directories("${OPENAIR2_DIR}/UTIL/OSA")
|
||||
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/LISTS")
|
||||
include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
|
||||
@@ -1119,8 +1117,29 @@ include_directories("${OPENAIR2_DIR}/UTIL/OMV")
|
||||
include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES")
|
||||
include_directories("${OPENAIR_DIR}")
|
||||
|
||||
# Utilities Library
|
||||
# flexran
|
||||
################
|
||||
# Make lfds as a own source code (even if it is a outside library)
|
||||
# only user: Flexran, please don't use lfds in any other component
|
||||
###################################################################
|
||||
|
||||
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)
|
||||
|
||||
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}
|
||||
)
|
||||
|
||||
target_include_directories(LFDS7 PRIVATE "${lfds7}")
|
||||
# set the version of protobuf messages, V3 not supported yet
|
||||
add_list1_option(FLPT_VERSION V2 "FLPT MSG protobuf grammar version" V2 V3)
|
||||
|
||||
@@ -1168,6 +1187,9 @@ add_library(FLPT_MSG
|
||||
${FLPT_OAI_generated}
|
||||
${FLPT_source}
|
||||
)
|
||||
target_link_libraries(FLPT_MSG LFDS7)
|
||||
add_dependencies(FLPT_MSG LFDS7)
|
||||
|
||||
set(FLPT_MSG_LIB FLPT_MSG)
|
||||
#message("prpt c dir is : ${FLPT_C_DIR}")
|
||||
include_directories (${FLPT_C_DIR})
|
||||
@@ -1179,6 +1201,7 @@ add_library(ASYNC_IF
|
||||
${OPENAIR2_DIR}/UTIL/ASYNC_IF/ringbuffer_queue.c
|
||||
)
|
||||
set(ASYNC_IF_LIB ASYNC_IF)
|
||||
target_include_directories(ASYNC_IF PRIVATE "${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
|
||||
include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
|
||||
|
||||
add_library(FLEXRAN_AGENT
|
||||
@@ -1201,7 +1224,9 @@ add_library(FLEXRAN_AGENT
|
||||
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c
|
||||
)
|
||||
add_dependencies(FLEXRAN_AGENT rrc_flag)
|
||||
add_dependencies(FLEXRAN_AGENT rrc_flag ASYNC_IF)
|
||||
target_link_libraries(FLEXRAN_AGENT ASYNC_IF LFDS7)
|
||||
target_include_directories(FLEXRAN_AGENT PRIVATE "${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
|
||||
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
|
||||
add_library(flapp_sample SHARED
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c
|
||||
@@ -1261,19 +1286,14 @@ set(FSPT_MSG_LIB FSPT_MSG)
|
||||
message("fspt c dir is : ${FSPT_C_DIR}")
|
||||
include_directories (${FSPT_C_DIR})
|
||||
|
||||
# add_library(ASYNC_IF
|
||||
# ${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c
|
||||
# ${OPENAIR2_DIR}/UTIL/ASYNC_IF/link_manager.c
|
||||
# ${OPENAIR2_DIR}/UTIL/ASYNC_IF/message_queue.c
|
||||
# ${OPENAIR2_DIR}/UTIL/ASYNC_IF/ringbuffer_queue.c
|
||||
# )
|
||||
# set(ASYNC_IF_LIB ASYNC_IF)
|
||||
# include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
|
||||
|
||||
set(PROTOBUF_LIB "protobuf-c")
|
||||
|
||||
#set(PROTOBUF_LIB "protobuf") #for Cpp
|
||||
|
||||
###########
|
||||
# Utilities
|
||||
###############
|
||||
|
||||
add_library(HASHTABLE
|
||||
${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
|
||||
${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
|
||||
@@ -1935,7 +1955,6 @@ set(L2_SRC
|
||||
${PDCP_DIR}/pdcp_primitives.c
|
||||
${PDCP_DIR}/pdcp_util.c
|
||||
${PDCP_DIR}/pdcp_security.c
|
||||
${PDCP_DIR}/pdcp_netlink.c
|
||||
${OPENAIR2_DIR}/LAYER2/openair2_proc.c
|
||||
# ${RRC_DIR}/rrc_UE.c
|
||||
${RRC_DIR}/rrc_eNB.c
|
||||
@@ -1990,7 +2009,6 @@ set(L2_SRC_UE
|
||||
${PDCP_DIR}/pdcp_primitives.c
|
||||
${PDCP_DIR}/pdcp_util.c
|
||||
${PDCP_DIR}/pdcp_security.c
|
||||
${PDCP_DIR}/pdcp_netlink.c
|
||||
${RRC_DIR}/rrc_UE.c
|
||||
${RRC_DIR}/rrc_common.c
|
||||
${RRC_DIR}/L2_interface_common.c
|
||||
@@ -2530,43 +2548,6 @@ add_library(LIB_5GNAS_GNB
|
||||
)
|
||||
target_link_libraries(LIB_5GNAS_GNB SECU_CN ${CRYPTO_LIBRARIES})
|
||||
|
||||
# Make lfds as a own source code (even if it is a outside library)
|
||||
# For better intergration with compilation flags & structure of cmake
|
||||
###################################################################
|
||||
set(lfds ${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/src/)
|
||||
file(GLOB lfds_queue ${lfds}/lfds611_queue/*.c)
|
||||
file(GLOB lfds_ring ${lfds}/lfds611_ringbuffer/*.c)
|
||||
file(GLOB lfds_slist ${lfds}/lfds611_slist/*.c)
|
||||
file(GLOB lfds_stack ${lfds}/lfds611_stack/*.c)
|
||||
file(GLOB lfds_freelist ${lfds}/lfds611_freelist/*.c)
|
||||
|
||||
include_directories(${lfds})
|
||||
add_library(LFDS
|
||||
${lfds_queue} ${lfds_ring} ${lfds_slist} ${lfds_stack} ${lfds_freelist}
|
||||
${lfds}/lfds611_liblfds/lfds611_liblfds_abstraction_test_helpers.c
|
||||
${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_free.c
|
||||
${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_malloc.c
|
||||
${lfds}/lfds611_abstraction/lfds611_abstraction_free.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}
|
||||
)
|
||||
|
||||
add_library(SIMU_COMMON
|
||||
${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c
|
||||
${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c
|
||||
@@ -2760,8 +2741,8 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer)
|
||||
target_link_libraries (lte-softmodem
|
||||
-Wl,--start-group
|
||||
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U F1AP_LIB F1AP SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
|
||||
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB}
|
||||
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB}
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES})
|
||||
@@ -2804,8 +2785,8 @@ target_link_libraries (ocp-enb
|
||||
-Wl,--start-group
|
||||
|
||||
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
|
||||
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB}
|
||||
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU_COMMON
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB}
|
||||
-Wl,--end-group z dl)
|
||||
target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB})
|
||||
|
||||
@@ -2870,8 +2851,8 @@ target_link_libraries (lte-uesoftmodem
|
||||
-Wl,--start-group
|
||||
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB
|
||||
SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
|
||||
PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES}
|
||||
PHY_UE PHY_RU L2_UE L2_LTE SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ATLAS_LIBRARIES}
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES})
|
||||
@@ -2913,8 +2894,8 @@ add_executable(nr-softmodem
|
||||
|
||||
target_link_libraries (nr-softmodem
|
||||
-Wl,--start-group
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${FLEXRAN_AGENT_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
|
||||
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
|
||||
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${FSPT_MSG_LIB}
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2953,8 +2934,8 @@ add_executable(ocp-gnb
|
||||
|
||||
target_link_libraries (ocp-gnb
|
||||
-Wl,--start-group
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
|
||||
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
|
||||
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB SIMU_COMMON
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2998,11 +2979,11 @@ add_executable(nr-uesoftmodem
|
||||
target_link_libraries (nr-uesoftmodem
|
||||
-Wl,--start-group
|
||||
RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
|
||||
PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
|
||||
PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
|
||||
NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ATLAS_LIBRARIES}
|
||||
NFAPI_USER_LIB S1AP_LIB S1AP_ENB
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB}
|
||||
${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB}
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
target_link_libraries (nr-uesoftmodem ${LIBXML2_LIBRARIES})
|
||||
@@ -3032,7 +3013,7 @@ add_executable(dlsim_tm4
|
||||
${T_SOURCE}
|
||||
)
|
||||
target_link_libraries (dlsim_tm4
|
||||
-Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY LFDS ITTI -Wl,--end-group
|
||||
-Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group
|
||||
pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${T_LIB}
|
||||
)
|
||||
|
||||
@@ -3236,7 +3217,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr
|
||||
${NFAPI_USER_DIR}/nfapi.c
|
||||
)
|
||||
target_link_libraries (${myExe}
|
||||
-Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU LFDS ITTI LFDS7 -Wl,--end-group
|
||||
-Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group
|
||||
pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} dl
|
||||
)
|
||||
|
||||
@@ -3251,7 +3232,7 @@ add_executable(test_epc_generate_scenario
|
||||
${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h
|
||||
)
|
||||
target_link_libraries (test_epc_generate_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB PHY LFDS ITTI L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB PHY ITTI L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
)
|
||||
|
||||
add_executable(test_epc_play_scenario
|
||||
@@ -3270,7 +3251,7 @@ add_executable(test_epc_play_scenario
|
||||
)
|
||||
target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
|
||||
target_link_libraries (test_epc_play_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ITTI -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE ITTI -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
)
|
||||
|
||||
|
||||
@@ -3290,7 +3271,7 @@ foreach(myExe s1ap
|
||||
${OPENAIR3_DIR}/TEST/test_${myExe}.c
|
||||
)
|
||||
target_link_libraries (test_${myExe}
|
||||
-Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
-Wl,--start-group SECU_CN UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
|
||||
)
|
||||
endforeach(myExe)
|
||||
|
||||
@@ -3311,12 +3292,12 @@ if (${T_TRACER})
|
||||
ITTI RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP
|
||||
params_libconfig oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
|
||||
oai_eth_transpro oai_mobipass tcp_bridge tcp_bridge_oai
|
||||
coding FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE UTIL OMG_SUMO
|
||||
coding FLPT_MSG FLEXRAN_AGENT HASHTABLE UTIL OMG_SUMO
|
||||
SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
|
||||
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR NGAP_GNB
|
||||
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB
|
||||
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc dfts)
|
||||
if (TARGET ${i})
|
||||
add_dependencies(${i} generate_T)
|
||||
@@ -3424,8 +3405,8 @@ add_executable(nr-ittisim
|
||||
|
||||
target_link_libraries (nr-ittisim
|
||||
-Wl,--start-group
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${FLPT_MSG_LIB} ${FLEXRAN_AGENT_LIB} ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB
|
||||
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
|
||||
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${FSPT_MSG_LIB}
|
||||
PHY_NR_UE SCHED_NR_UE_LIB NR_L2_UE
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
building liblfds
|
||||
================
|
||||
|
||||
Windows (user-mode)
|
||||
===================
|
||||
1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition (or
|
||||
later versions) to load "liblfds.sln". The "Win32" platform is x86,
|
||||
the "x64" platform is x64.
|
||||
|
||||
2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
|
||||
you'll need to have run setenv.bat or the appropriate vcvars*.bat first;
|
||||
you can build for x64/64-bit and x86/32-bit - just run the correct batch
|
||||
file).
|
||||
|
||||
Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean". You need
|
||||
to clean between switching targets.
|
||||
|
||||
Windows (kernel)
|
||||
================
|
||||
Use the Windows Driver Kit "build" command. Prior to running "build",
|
||||
if you wish to build a static library, run the batch file
|
||||
"runme_before_win_kernel_static_lib_build.bat"; if you wish to
|
||||
build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat".
|
||||
|
||||
The Windows kernel build system is rather limited and rather than
|
||||
really rather messing up the directory/file structure just for the
|
||||
Windows kernel platform, I've instead arranged it that these batch
|
||||
files do the necessary work so that "build" will work.
|
||||
|
||||
The batch files are idempotent; you can run them as often as you
|
||||
like, in any order, at any time (before or after builds), and they'll
|
||||
do the right thing. You need to clean between switching targets.
|
||||
|
||||
Linux
|
||||
=====
|
||||
Use GNUmake to run "makefile.linux". Targets are "arrel", "ardbg",
|
||||
"sorel", "sodbg" and "clean". You need to clean between switching
|
||||
targets.
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
DIRS = src
|
||||
|
||||
@@ -1,334 +0,0 @@
|
||||
#ifndef __LIBLFDS611_H
|
||||
|
||||
/***** library header *****/
|
||||
#define LFDS611_RELEASE_NUMBER_STRING "6.1.1"
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_abstraction *****/
|
||||
|
||||
/***** defines *****/
|
||||
#if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
// TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
typedef unsigned __int64 lfds611_atom_t;
|
||||
#define LFDS611_INLINE __forceinline
|
||||
#define LFDS611_ALIGN(alignment) __declspec( align(alignment) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 8
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 16
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD _ReadBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_STORE _WriteBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_FULL _ReadWriteBarrier()
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD _mm_lfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE _mm_sfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL _mm_mfence()
|
||||
#endif
|
||||
|
||||
#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
// TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
typedef unsigned long int lfds611_atom_t;
|
||||
#define LFDS611_INLINE __forceinline
|
||||
#define LFDS611_ALIGN(alignment) __declspec( align(alignment) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 4
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 8
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD _ReadBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_STORE _WriteBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_FULL _ReadWriteBarrier()
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD _mm_lfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE _mm_sfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL _mm_mfence()
|
||||
|
||||
// TRD : this define is documented but missing in Microsoft Platform SDK v7.0
|
||||
#define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
|
||||
#endif
|
||||
|
||||
#if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
// TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wdm.h>
|
||||
typedef unsigned __int64 lfds611_atom_t;
|
||||
#define LFDS611_INLINE __forceinline
|
||||
#define LFDS611_ALIGN(alignment) __declspec( align(alignment) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 8
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 16
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD _ReadBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_STORE _WriteBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_FULL _ReadWriteBarrier()
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD _mm_lfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE _mm_sfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL _mm_mfence()
|
||||
#endif
|
||||
|
||||
#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
// TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wdm.h>
|
||||
typedef unsigned long int lfds611_atom_t;
|
||||
#define LFDS611_INLINE __forceinline
|
||||
#define LFDS611_ALIGN(alignment) __declspec( align(alignment) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 4
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 8
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD _ReadBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_STORE _WriteBarrier()
|
||||
#define LFDS611_BARRIER_COMPILER_FULL _ReadWriteBarrier()
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD _mm_lfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE _mm_sfence()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL _mm_mfence()
|
||||
|
||||
// TRD : this define is documented but missing in Microsoft Platform SDK v7.0
|
||||
#define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
|
||||
#endif
|
||||
|
||||
#if (defined __unix__ && defined __x86_64__ && __GNUC__)
|
||||
// TRD : any UNIX with GCC on x64
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
typedef unsigned long long int lfds611_atom_t;
|
||||
#define LFDS611_INLINE inline
|
||||
#define LFDS611_ALIGN(alignment) __attribute__( (aligned(alignment)) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 8
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 16
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#if (defined __unix__ && defined __i386__ && __GNUC__)
|
||||
// TRD : any UNIX with GCC on x86
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
typedef unsigned long int lfds611_atom_t;
|
||||
#define LFDS611_INLINE inline
|
||||
#define LFDS611_ALIGN(alignment) __attribute__( (aligned(alignment)) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 4
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 8
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#if (defined __unix__ && defined __arm__ && __GNUC__)
|
||||
// TRD : any UNIX with GCC on ARM
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
typedef unsigned long int lfds611_atom_t;
|
||||
#define LFDS611_INLINE inline
|
||||
#define LFDS611_ALIGN(alignment) __attribute__( (aligned(alignment)) )
|
||||
#define LFDS611_ALIGN_SINGLE_POINTER 4
|
||||
#define LFDS611_ALIGN_DOUBLE_POINTER 8
|
||||
#define LFDS611_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" )
|
||||
#define LFDS611_BARRIER_PROCESSOR_LOAD __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_STORE __sync_synchronize()
|
||||
#define LFDS611_BARRIER_PROCESSOR_FULL __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#define LFDS611_BARRIER_LOAD LFDS611_BARRIER_COMPILER_LOAD; LFDS611_BARRIER_PROCESSOR_LOAD; LFDS611_BARRIER_COMPILER_LOAD
|
||||
#define LFDS611_BARRIER_STORE LFDS611_BARRIER_COMPILER_STORE; LFDS611_BARRIER_PROCESSOR_STORE; LFDS611_BARRIER_COMPILER_STORE
|
||||
#define LFDS611_BARRIER_FULL LFDS611_BARRIER_COMPILER_FULL; LFDS611_BARRIER_PROCESSOR_FULL; LFDS611_BARRIER_COMPILER_FULL
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_data_structure_validity {
|
||||
LFDS611_VALIDITY_VALID,
|
||||
LFDS611_VALIDITY_INVALID_LOOP,
|
||||
LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS,
|
||||
LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
|
||||
LFDS611_VALIDITY_INVALID_TEST_DATA
|
||||
};
|
||||
|
||||
/***** structs *****/
|
||||
struct lfds611_validation_info {
|
||||
lfds611_atom_t
|
||||
min_elements,
|
||||
max_elements;
|
||||
};
|
||||
|
||||
/***** public prototypes *****/
|
||||
void *lfds611_abstraction_malloc( size_t size );
|
||||
void lfds611_abstraction_free( void *memory );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_freelist *****/
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_freelist_query_type {
|
||||
LFDS611_FREELIST_QUERY_ELEMENT_COUNT,
|
||||
LFDS611_FREELIST_QUERY_VALIDATE
|
||||
};
|
||||
|
||||
/***** incomplete types *****/
|
||||
struct lfds611_freelist_state;
|
||||
struct lfds611_freelist_element;
|
||||
|
||||
/***** public prototypes *****/
|
||||
int lfds611_freelist_new( struct lfds611_freelist_state **fs, lfds611_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state );
|
||||
void lfds611_freelist_use( struct lfds611_freelist_state *fs );
|
||||
void lfds611_freelist_delete( struct lfds611_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
lfds611_atom_t lfds611_freelist_new_elements( struct lfds611_freelist_state *fs, lfds611_atom_t number_elements );
|
||||
|
||||
struct lfds611_freelist_element *lfds611_freelist_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe );
|
||||
struct lfds611_freelist_element *lfds611_freelist_guaranteed_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe );
|
||||
void lfds611_freelist_push( struct lfds611_freelist_state *fs, struct lfds611_freelist_element *fe );
|
||||
|
||||
void *lfds611_freelist_get_user_data_from_element( struct lfds611_freelist_element *fe, void **user_data );
|
||||
void lfds611_freelist_set_user_data_in_element( struct lfds611_freelist_element *fe, void *user_data );
|
||||
|
||||
void lfds611_freelist_query( struct lfds611_freelist_state *fs, enum lfds611_freelist_query_type query_type, void *query_input, void *query_output );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_liblfds *****/
|
||||
|
||||
/***** public prototypes *****/
|
||||
void lfds611_liblfds_abstraction_test_helper_increment_non_atomic( lfds611_atom_t *shared_counter );
|
||||
void lfds611_liblfds_abstraction_test_helper_increment_atomic( volatile lfds611_atom_t *shared_counter );
|
||||
void lfds611_liblfds_abstraction_test_helper_cas( volatile lfds611_atom_t *shared_counter, lfds611_atom_t *local_counter );
|
||||
void lfds611_liblfds_abstraction_test_helper_dcas( volatile lfds611_atom_t *shared_counter, lfds611_atom_t *local_counter );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_queue *****/
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_queue_query_type {
|
||||
LFDS611_QUEUE_QUERY_ELEMENT_COUNT,
|
||||
LFDS611_QUEUE_QUERY_VALIDATE
|
||||
};
|
||||
|
||||
/***** incomplete types *****/
|
||||
struct lfds611_queue_state;
|
||||
|
||||
/***** public prototypes *****/
|
||||
int lfds611_queue_new( struct lfds611_queue_state **sq, lfds611_atom_t number_elements );
|
||||
void lfds611_queue_use( struct lfds611_queue_state *qs );
|
||||
void lfds611_queue_delete( struct lfds611_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
int lfds611_queue_enqueue( struct lfds611_queue_state *qs, void *user_data );
|
||||
int lfds611_queue_guaranteed_enqueue( struct lfds611_queue_state *qs, void *user_data );
|
||||
int lfds611_queue_dequeue( struct lfds611_queue_state *qs, void **user_data );
|
||||
|
||||
void lfds611_queue_query( struct lfds611_queue_state *qs, enum lfds611_queue_query_type query_type, void *query_input, void *query_output );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_ringbuffer *****/
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_ringbuffer_query_type {
|
||||
LFDS611_RINGBUFFER_QUERY_VALIDATE
|
||||
};
|
||||
|
||||
/***** incomplete types *****/
|
||||
struct lfds611_ringbuffer_state;
|
||||
|
||||
/***** public prototypes *****/
|
||||
int lfds611_ringbuffer_new( struct lfds611_ringbuffer_state **rs, lfds611_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state );
|
||||
void lfds611_ringbuffer_use( struct lfds611_ringbuffer_state *rs );
|
||||
void lfds611_ringbuffer_delete( struct lfds611_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
struct lfds611_freelist_element *lfds611_ringbuffer_get_read_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element **fe );
|
||||
struct lfds611_freelist_element *lfds611_ringbuffer_get_write_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element **fe, int *overwrite_flag );
|
||||
|
||||
void lfds611_ringbuffer_put_read_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element *fe );
|
||||
void lfds611_ringbuffer_put_write_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element *fe );
|
||||
|
||||
void lfds611_ringbuffer_query( struct lfds611_ringbuffer_state *rs, enum lfds611_ringbuffer_query_type query_type, void *query_input, void *query_output );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_slist *****/
|
||||
|
||||
/***** incomplete types *****/
|
||||
struct lfds611_slist_state;
|
||||
struct lfds611_slist_element;
|
||||
|
||||
/***** public prototypes *****/
|
||||
int lfds611_slist_new( struct lfds611_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
void lfds611_slist_use( struct lfds611_slist_state *ss );
|
||||
void lfds611_slist_delete( struct lfds611_slist_state *ss );
|
||||
|
||||
struct lfds611_slist_element *lfds611_slist_new_head( struct lfds611_slist_state *ss, void *user_data );
|
||||
struct lfds611_slist_element *lfds611_slist_new_next( struct lfds611_slist_element *se, void *user_data );
|
||||
|
||||
int lfds611_slist_logically_delete_element( struct lfds611_slist_state *ss, struct lfds611_slist_element *se );
|
||||
void lfds611_slist_single_threaded_physically_delete_all_elements( struct lfds611_slist_state *ss );
|
||||
|
||||
int lfds611_slist_get_user_data_from_element( struct lfds611_slist_element *se, void **user_data );
|
||||
int lfds611_slist_set_user_data_in_element( struct lfds611_slist_element *se, void *user_data );
|
||||
|
||||
struct lfds611_slist_element *lfds611_slist_get_head( struct lfds611_slist_state *ss, struct lfds611_slist_element **se );
|
||||
struct lfds611_slist_element *lfds611_slist_get_next( struct lfds611_slist_element *se, struct lfds611_slist_element **next_se );
|
||||
struct lfds611_slist_element *lfds611_slist_get_head_and_then_next( struct lfds611_slist_state *ss, struct lfds611_slist_element **se );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***** lfds611_stack *****/
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_stack_query_type {
|
||||
LFDS611_STACK_QUERY_ELEMENT_COUNT,
|
||||
LFDS611_STACK_QUERY_VALIDATE
|
||||
};
|
||||
|
||||
/***** incomplete types *****/
|
||||
struct lfds611_stack_state;
|
||||
|
||||
/***** public prototypes *****/
|
||||
int lfds611_stack_new( struct lfds611_stack_state **ss, lfds611_atom_t number_elements );
|
||||
void lfds611_stack_use( struct lfds611_stack_state *ss );
|
||||
void lfds611_stack_delete( struct lfds611_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
void lfds611_stack_clear( struct lfds611_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
int lfds611_stack_push( struct lfds611_stack_state *ss, void *user_data );
|
||||
int lfds611_stack_guaranteed_push( struct lfds611_stack_state *ss, void *user_data );
|
||||
int lfds611_stack_pop( struct lfds611_stack_state *ss, void **user_data );
|
||||
|
||||
void lfds611_stack_query( struct lfds611_stack_state *ss, enum lfds611_stack_query_type query_type, void *query_input, void *query_output );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define __LIBLFDS611_H
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
EXPORTS
|
||||
|
||||
lfds611_liblfds_abstraction_test_helper_increment_non_atomic = lfds611_liblfds_abstraction_test_helper_increment_non_atomic @1
|
||||
lfds611_liblfds_abstraction_test_helper_increment_atomic = lfds611_liblfds_abstraction_test_helper_increment_atomic @2
|
||||
lfds611_liblfds_abstraction_test_helper_cas = lfds611_liblfds_abstraction_test_helper_cas @3
|
||||
lfds611_liblfds_abstraction_test_helper_dcas = lfds611_liblfds_abstraction_test_helper_dcas @4
|
||||
|
||||
lfds611_freelist_delete = lfds611_freelist_delete @5
|
||||
lfds611_freelist_get_user_data_from_element = lfds611_freelist_get_user_data_from_element @6
|
||||
lfds611_freelist_guaranteed_pop = lfds611_freelist_guaranteed_pop @7
|
||||
lfds611_freelist_new = lfds611_freelist_new @8
|
||||
lfds611_freelist_new_elements = lfds611_freelist_new_elements @9
|
||||
lfds611_freelist_pop = lfds611_freelist_pop @10
|
||||
lfds611_freelist_push = lfds611_freelist_push @11
|
||||
lfds611_freelist_query = lfds611_freelist_query @12
|
||||
lfds611_freelist_set_user_data_in_element = lfds611_freelist_set_user_data_in_element @13
|
||||
lfds611_freelist_use = lfds611_freelist_use @14
|
||||
|
||||
lfds611_queue_delete = lfds611_queue_delete @15
|
||||
lfds611_queue_dequeue = lfds611_queue_dequeue @16
|
||||
lfds611_queue_enqueue = lfds611_queue_enqueue @17
|
||||
lfds611_queue_guaranteed_enqueue = lfds611_queue_guaranteed_enqueue @18
|
||||
lfds611_queue_new = lfds611_queue_new @19
|
||||
lfds611_queue_query = lfds611_queue_query @20
|
||||
lfds611_queue_use = lfds611_queue_use @21
|
||||
|
||||
lfds611_ringbuffer_delete = lfds611_ringbuffer_delete @22
|
||||
lfds611_ringbuffer_get_read_element = lfds611_ringbuffer_get_read_element @23
|
||||
lfds611_ringbuffer_get_write_element = lfds611_ringbuffer_get_write_element @24
|
||||
lfds611_ringbuffer_new = lfds611_ringbuffer_new @25
|
||||
lfds611_ringbuffer_put_read_element = lfds611_ringbuffer_put_read_element @26
|
||||
lfds611_ringbuffer_put_write_element = lfds611_ringbuffer_put_write_element @27
|
||||
lfds611_ringbuffer_query = lfds611_ringbuffer_query @28
|
||||
lfds611_ringbuffer_use = lfds611_ringbuffer_use @29
|
||||
|
||||
lfds611_slist_delete = lfds611_slist_delete @30
|
||||
lfds611_slist_get_head = lfds611_slist_get_head @31
|
||||
lfds611_slist_get_head_and_then_next = lfds611_slist_get_head_and_then_next @32
|
||||
lfds611_slist_get_next = lfds611_slist_get_next @33
|
||||
lfds611_slist_get_user_data_from_element = lfds611_slist_get_user_data_from_element @34
|
||||
lfds611_slist_logically_delete_element = lfds611_slist_logically_delete_element @35
|
||||
lfds611_slist_new = lfds611_slist_new @36
|
||||
lfds611_slist_new_head = lfds611_slist_new_head @37
|
||||
lfds611_slist_new_next = lfds611_slist_new_next @38
|
||||
lfds611_slist_set_user_data_in_element = lfds611_slist_set_user_data_in_element @39
|
||||
lfds611_slist_single_threaded_physically_delete_all_elements = lfds611_slist_single_threaded_physically_delete_all_elements @40
|
||||
lfds611_slist_use = lfds611_slist_use @41
|
||||
|
||||
lfds611_stack_clear = lfds611_stack_clear @42
|
||||
lfds611_stack_delete = lfds611_stack_delete @43
|
||||
lfds611_stack_guaranteed_push = lfds611_stack_guaranteed_push @44
|
||||
lfds611_stack_new = lfds611_stack_new @45
|
||||
lfds611_stack_pop = lfds611_stack_pop @46
|
||||
lfds611_stack_push = lfds611_stack_push @47
|
||||
lfds611_stack_query = lfds611_stack_query @48
|
||||
lfds611_stack_use = lfds611_stack_use @49
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds611", "liblfds611.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug DLL|Win32 = Debug DLL|Win32
|
||||
Debug DLL|x64 = Debug DLL|x64
|
||||
Debug Lib|Win32 = Debug Lib|Win32
|
||||
Debug Lib|x64 = Debug Lib|x64
|
||||
Release DLL|Win32 = Release DLL|Win32
|
||||
Release DLL|x64 = Release DLL|x64
|
||||
Release Lib|Win32 = Release Lib|Win32
|
||||
Release Lib|x64 = Release Lib|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,800 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="liblfds611"
|
||||
ProjectGUID="{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
|
||||
RootNamespace="liblfds"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug Lib|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions="/wx"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug Lib|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
SmallerTypeCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions="/wx"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release Lib|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions="/wx"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release Lib|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions="/wx"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug DLL|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="msvcrtd.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
ModuleDefinitionFile="$(ProjectDir)\liblfds611.def"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug DLL|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
SmallerTypeCheck="true"
|
||||
RuntimeLibrary="3"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="msvcrtd.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
ModuleDefinitionFile="$(ProjectDir)\liblfds611.def"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release DLL|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="msvcrt.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
ModuleDefinitionFile="$(ProjectDir)\liblfds611.def"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release DLL|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\inc""
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="msvcrt.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
ModuleDefinitionFile="$(ProjectDir)\liblfds611.def"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="inc"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\inc\liblfds611.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="src"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\liblfds611_internal.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="lfds611_abstraction"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_abstraction\lfds611_abstraction_free.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_abstraction\lfds611_abstraction_internal_body.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_abstraction\lfds611_abstraction_internal_wrapper.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_abstraction\lfds611_abstraction_malloc.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_freelist"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_delete.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_get_and_set.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_new.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_pop_push.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_freelist\lfds611_freelist_query.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_queue"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_queue\lfds611_queue_delete.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_queue\lfds611_queue_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_queue\lfds611_queue_new.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_queue\lfds611_queue_query.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_queue\lfds611_queue_queue.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_ringbuffer"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_ringbuffer\lfds611_ringbuffer_delete.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_ringbuffer\lfds611_ringbuffer_get_and_put.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_ringbuffer\lfds611_ringbuffer_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_ringbuffer\lfds611_ringbuffer_new.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_ringbuffer\lfds611_ringbuffer_query.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_slist"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_slist\lfds611_slist_delete.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_slist\lfds611_slist_get_and_set.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_slist\lfds611_slist_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_slist\lfds611_slist_link.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_slist\lfds611_slist_new.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_stack"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_stack\lfds611_stack_delete.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_stack\lfds611_stack_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_stack\lfds611_stack_new.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_stack\lfds611_stack_push_pop.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_stack\lfds611_stack_query.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="lfds611_liblfds"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_liblfds\lfds611_liblfds_abstraction_test_helpers.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_liblfds\lfds611_liblfds_aligned_free.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_liblfds\lfds611_liblfds_aligned_malloc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\lfds611_liblfds\lfds611_liblfds_internal.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,111 +0,0 @@
|
||||
##### paths #####
|
||||
OUTDIR := .
|
||||
BINDIR = $(OUTDIR)/bin
|
||||
OBJDIR = $(OUTDIR)/obj
|
||||
INCDIR = inc
|
||||
SRCDIR = src
|
||||
|
||||
##### misc #####
|
||||
QUIETLY = 1>/dev/null 2>/dev/null
|
||||
|
||||
##### sources, objects and libraries #####
|
||||
BINNAME = liblfds611
|
||||
AR_BINARY = $(BINDIR)/$(BINNAME).a
|
||||
$(info $(AR_BINARY))
|
||||
SO_BINARY = $(BINDIR)/$(BINNAME).so
|
||||
SRCDIRS = lfds611_abstraction lfds611_freelist lfds611_liblfds lfds611_queue lfds611_ringbuffer lfds611_slist lfds611_stack
|
||||
# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order
|
||||
# of source files matters! this is because it leads to the ordering of objects in the library and
|
||||
# that in turn, since the data structures all use the freelist API and the abstraction API, has to be
|
||||
# correct
|
||||
# TRD : lfds611_abstraction_cas.c lfds611_abstraction_dcas.c lfds611_abstraction_increment.c are inlined and are compiled by every C file
|
||||
SOURCES = lfds611_queue_delete.c lfds611_queue_new.c lfds611_queue_query.c lfds611_queue_queue.c \
|
||||
lfds611_ringbuffer_delete.c lfds611_ringbuffer_get_and_put.c lfds611_ringbuffer_new.c lfds611_ringbuffer_query.c \
|
||||
lfds611_slist_delete.c lfds611_slist_get_and_set.c lfds611_slist_link.c lfds611_slist_new.c \
|
||||
lfds611_stack_delete.c lfds611_stack_new.c lfds611_stack_push_pop.c lfds611_stack_query.c \
|
||||
lfds611_freelist_delete.c lfds611_freelist_get_and_set.c lfds611_freelist_new.c lfds611_freelist_query.c lfds611_freelist_pop_push.c \
|
||||
lfds611_liblfds_abstraction_test_helpers.c lfds611_liblfds_aligned_free.c lfds611_liblfds_aligned_malloc.c \
|
||||
lfds611_abstraction_free.c lfds611_abstraction_malloc.c
|
||||
OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
|
||||
|
||||
##### CPU variants #####
|
||||
UNAME = $(shell uname -m)
|
||||
GCCARCH = -march=$(UNAME)
|
||||
|
||||
ifeq ($(UNAME),x86_64)
|
||||
GCCARCH = -march=core2
|
||||
endif
|
||||
|
||||
ifeq ($(findstring arm,$(UNAME)),arm)
|
||||
GCCARCH = -march=armv6k -marm
|
||||
endif
|
||||
|
||||
##### tools #####
|
||||
MAKE = make
|
||||
MFLAGS =
|
||||
|
||||
DG = gcc
|
||||
DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)"
|
||||
|
||||
CC = gcc
|
||||
CBASE = -Wall -Wno-unknown-pragmas -std=c99 $(GCCARCH) -pthread -c -I"$(SRCDIR)" -I"$(INCDIR)"
|
||||
CFREL = -O2 -finline-functions -Wno-strict-aliasing
|
||||
CFDBG = -O0 -g
|
||||
|
||||
AR = ar
|
||||
AFLAGS = -rcs
|
||||
|
||||
LD = gcc
|
||||
LFBASE = -Wall -std=c99 -shared
|
||||
LFREL = -O2 -s
|
||||
LFDBG = -O0 -g
|
||||
|
||||
##### rel/dbg .a/.so variants #####
|
||||
ifeq ($(findstring so,$(MAKECMDGOALS)),so)
|
||||
CBASE := $(CBASE) -fpic
|
||||
endif
|
||||
|
||||
CFLAGS = $(CBASE) $(CFDBG)
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
|
||||
ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
|
||||
CFLAGS = $(CBASE) $(CFREL)
|
||||
LFLAGS = $(LFBASE) $(LFREL)
|
||||
endif
|
||||
|
||||
##### search paths #####
|
||||
vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
|
||||
|
||||
##### implicit rules #####
|
||||
$(OBJDIR)/%.o : %.c
|
||||
@echo "Compiling $<"
|
||||
@$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
|
||||
@$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
##### explicit rules #####
|
||||
$(AR_BINARY) : $(OBJECTS)
|
||||
@echo "Creating $(AR_BINARY)"
|
||||
@$(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS)
|
||||
|
||||
$(SO_BINARY) : $(OBJECTS)
|
||||
@echo "Creating $(SO_BINARY)"
|
||||
$(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY)
|
||||
|
||||
##### phony #####
|
||||
.PHONY : clean arrel ardbg sorel sodbg
|
||||
|
||||
clean :
|
||||
@rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d
|
||||
|
||||
arrel : $(AR_BINARY)
|
||||
ardbg : $(AR_BINARY)
|
||||
|
||||
sorel : $(SO_BINARY)
|
||||
sodbg : $(SO_BINARY)
|
||||
|
||||
##### dependencies #####
|
||||
-include $(DEPENDS)
|
||||
|
||||
##### notes #####
|
||||
# TRD : we use -std=c99 purely to permit C++ style comments
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
##### paths #####
|
||||
BINDIR = bin
|
||||
INCDIR = inc
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
##### misc #####
|
||||
QUIETLY = 1>nul 2>nul
|
||||
|
||||
##### sources, objects and libraries #####
|
||||
BINNAME = liblfds611
|
||||
LIB_BINARY = $(BINDIR)\$(BINNAME).lib
|
||||
DLL_BINARY = $(BINDIR)\$(BINNAME).dll
|
||||
SRCDIRS = lfds611_abstraction lfds611_freelist lfds611_liblfds lfds611_queue lfds611_ringbuffer lfds611_slist lfds611_stack
|
||||
# TRD : lfds611_abstraction_cas.c lfds611_abstraction_dcas.c lfds611_abstraction_increment.c are inlined and are compiled by every C file
|
||||
SOURCES = lfds611_abstraction_free.c lfds611_abstraction_malloc.c \
|
||||
lfds611_freelist_delete.c lfds611_freelist_get_and_set.c lfds611_freelist_new.c lfds611_freelist_query.c lfds611_freelist_pop_push.c \
|
||||
lfds611_liblfds_abstraction_test_helpers.c lfds611_liblfds_aligned_free.c lfds611_liblfds_aligned_malloc.c \
|
||||
lfds611_queue_delete.c lfds611_queue_new.c lfds611_queue_query.c lfds611_queue_queue.c \
|
||||
lfds611_ringbuffer_delete.c lfds611_ringbuffer_get_and_put.c lfds611_ringbuffer_new.c lfds611_ringbuffer_query.c \
|
||||
lfds611_slist_delete.c lfds611_slist_get_and_set.c lfds611_slist_link.c lfds611_slist_new.c \
|
||||
lfds611_stack_delete.c lfds611_stack_new.c lfds611_stack_push_pop.c lfds611_stack_query.c
|
||||
OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
|
||||
SYSLIBS = kernel32.lib
|
||||
|
||||
##### tools #####
|
||||
MAKE = make
|
||||
MFLAGS =
|
||||
|
||||
CC = cl
|
||||
CBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN
|
||||
CFREL = /Ox /DNDEBUG
|
||||
CFDBG = /Od /Gm /Zi /D_DEBUG
|
||||
|
||||
AR = lib
|
||||
AFLAGS = /nologo /subsystem:console /wx /verbose
|
||||
|
||||
LD = link
|
||||
LFBASE = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat
|
||||
LFREL = /incremental:no
|
||||
LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
|
||||
|
||||
##### variants #####
|
||||
CFLAGS = $(CBASE) $(CFDBG) /MTd
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
CLIB = libcmtd.lib
|
||||
|
||||
ifeq ($(MAKECMDGOALS),librel)
|
||||
CFLAGS = $(CBASE) $(CFREL) /MT
|
||||
LFLAGS = $(LFBASE) $(LFREL)
|
||||
CLIB = libcmt.lib
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),libdbg)
|
||||
CFLAGS = $(CBASE) $(CFDBG) /MTd
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
CLIB = libcmtd.lib
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),dllrel)
|
||||
CFLAGS = $(CBASE) $(CFREL) /MD
|
||||
LFLAGS = $(LFBASE) $(LFREL)
|
||||
CLIB = msvcrt.lib
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),dlldbg)
|
||||
CFLAGS = $(CBASE) $(CFDBG) /MDd
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
CLIB = msvcrtd.lib
|
||||
endif
|
||||
|
||||
##### search paths #####
|
||||
vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
|
||||
|
||||
##### implicit rules #####
|
||||
$(OBJDIR)/%.obj : %.c
|
||||
$(CC) $(CFLAGS) "/Fo$@" $<
|
||||
|
||||
##### explicit rules #####
|
||||
$(LIB_BINARY) : $(OBJECTS)
|
||||
$(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY)
|
||||
|
||||
$(DLL_BINARY) : $(OBJECTS)
|
||||
$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(OBJECTS) /out:$(DLL_BINARY)
|
||||
|
||||
##### phony #####
|
||||
.PHONY : clean librel libdbg dllrel dlldbg
|
||||
|
||||
clean :
|
||||
@erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY)
|
||||
|
||||
librel : $(LIB_BINARY)
|
||||
libdbg : $(LIB_BINARY)
|
||||
|
||||
dllrel : $(DLL_BINARY)
|
||||
dlldbg : $(DLL_BINARY)
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
introduction
|
||||
============
|
||||
Welcome to liblfds, a portable, license-free, lock-free data structure library
|
||||
written in C.
|
||||
|
||||
supported platforms
|
||||
===================
|
||||
Out-of-the-box ports are provided for;
|
||||
|
||||
Operating System CPU Toolchain Choices
|
||||
================ ============= =================
|
||||
Windows 64-bit x64 1. Microsoft Visual Studio
|
||||
2. Microsoft Windows SDK and GNUmake
|
||||
|
||||
Windows 32-bit x64, x86 1. Microsoft Visual Studio
|
||||
2. Visual C++ Express Edition
|
||||
3. Microsoft Windows SDK and GNUmake
|
||||
|
||||
Windows Kernel x64, x86 1. Windows Driver Kit
|
||||
|
||||
Linux 64-bit x64 1. GCC and GNUmake
|
||||
|
||||
Linux 32-bit ARM, x64, x86 1. GCC and GNUmake
|
||||
|
||||
For more information including version requirements, see the building guide (lfds).
|
||||
|
||||
data structures
|
||||
===============
|
||||
This release of liblfds provides the following;
|
||||
|
||||
* Freelist
|
||||
* Queue
|
||||
* Ringbuffer (each element read by a single reader)
|
||||
* Singly-linked list (logical delete only)
|
||||
* Stack
|
||||
|
||||
These are all many-readers, many-writers.
|
||||
|
||||
liblfds on-line
|
||||
===============
|
||||
On the liblfds home page, you will find the blog, a bugzilla, a forum, a
|
||||
mediawiki and the current and all historical releases.
|
||||
|
||||
The mediawiki contains comprehensive documentation for development, building,
|
||||
testing and porting.
|
||||
|
||||
http://www.liblfds.org
|
||||
|
||||
license
|
||||
=======
|
||||
There is no license. You are free to use this code in any way.
|
||||
|
||||
using
|
||||
=====
|
||||
Once built, there is a single header file, /inc/liblfds.h, which you must include
|
||||
in your source code, and a single library file /bin/liblfds.*, where the suffix
|
||||
depends on your platform and your build choice (static or dynamic), to which,
|
||||
if statically built, you must link directly or, if dynamically built, you must
|
||||
arrange your system such that the library can be found by the loader at run-time.
|
||||
|
||||
testing
|
||||
=======
|
||||
The library comes with a command line test and benchmark program. This program
|
||||
requires threads. As such, it is only suitable for platforms which can execute
|
||||
a command line binary and provide thread support. Currently this means the test
|
||||
and benchmark program works for all platforms except the Windows Kernel.
|
||||
|
||||
For documentation, see the testing and benchmarking guide in the mediawiki.
|
||||
|
||||
porting
|
||||
=======
|
||||
Both the test program and liblfds provide an abstraction layer which acts to
|
||||
mask platform differences. Porting is the act of implementing on your platform
|
||||
the functions which make up the abstraction layers. You do not need to port
|
||||
the test program to port liblfds, but obviously it is recommended, so you can
|
||||
test your port.
|
||||
|
||||
To support liblfds, your platform MUST support;
|
||||
|
||||
* atomic single-word* increment
|
||||
* atomic single-word compare-and-swap
|
||||
* atomic contiguous double-word compare-and-swap*
|
||||
* malloc and free
|
||||
* compiler directive for alignment of variables declared on the stack
|
||||
* compiler directives for compiler barriers and processor barriers
|
||||
|
||||
* A ''word'' here means a type equal in length to the platform pointer size.
|
||||
* This requirement excludes the Alpha, IA64, MIPS, PowerPC and SPARC platforms.
|
||||
|
||||
Also, your platform MAY support;
|
||||
|
||||
* compiler keyword for function inlining
|
||||
|
||||
To support the test programme, your platform MUST support;
|
||||
|
||||
* determining the number of logical cores
|
||||
* threads (starting and waiting on for completion)
|
||||
|
||||
For documentation, see the porting guide (lfds) in the mediawiki.
|
||||
|
||||
release history
|
||||
===============
|
||||
release 1, 25th September 2009, svn revision 1574.
|
||||
- initial release
|
||||
|
||||
release 2, 5th October 2009, svn revision 1599.
|
||||
- added abstraction layer for Windows kernel
|
||||
- minor code tidyups/fixes
|
||||
|
||||
release 3, 25th October 2009, svn revision 1652.
|
||||
- added singly linked list (logical delete only)
|
||||
- minor code tidyups/fixes
|
||||
|
||||
release 4, 7th December 2009, svn revision 1716.
|
||||
- added ARM support
|
||||
- added benchmarking functionality to the test program
|
||||
- fixed a profound and pervasive pointer
|
||||
declaration bug; earlier releases of liblfds
|
||||
*should not be used*
|
||||
|
||||
release 5, 19th December 2009, svn revision 1738.
|
||||
- fixed subtle queue bug, which also affected ringbuffer
|
||||
and caused data re-ordering under high load
|
||||
- added benchmarks for freelist, ringbuffer and stack
|
||||
|
||||
release 6, 29th December 2009, svn revision 1746.
|
||||
- fixed two implementation errors, which reduced performance,
|
||||
spotted by Codeplug from "http://cboard.cprogramming.com".
|
||||
|
||||
release 6.0.0, 18th December 2012, svn revision 2537
|
||||
- introduction of namespaces, e.g. the "lfds600_" prefix
|
||||
code otherwise COMPLETELY AND WHOLLY UNCHANGED
|
||||
this release is a stepping-stone to 6.1.0
|
||||
|
||||
release 6.0.1, 2nd January 2013, svn revision 3296
|
||||
- bug fix where an enum wasn't moved into the new namespacing policy
|
||||
|
||||
release 6.1.0, 31th December 2012, svn revision 2600
|
||||
- fixed all existing non-enhancement bugs
|
||||
- discovered some new bugs and fixed them too
|
||||
- a very few minor changes/enhancements
|
||||
|
||||
release 6.1.1, 2nd January 2013, svn revision 3297
|
||||
- crucial bug fix where compiler barriers for atomic operations
|
||||
were not brought over from 7.0.0 during backporting
|
||||
- minor fix for abstraction tests, two missing store barriers
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
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.
|
||||
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
@echo off
|
||||
rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_liblfds\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul
|
||||
copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
echo Windows kernel dynamic library build directory structure created.
|
||||
echo (Note the effects of this batch file are idempotent).
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
@echo off
|
||||
rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_liblfds\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y src\lfds611_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
|
||||
copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul
|
||||
erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul
|
||||
echo Windows kernel static library build directory structure created.
|
||||
echo (Note the effects of this batch file are idempotent).
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
MSC_WARNING_LEVEL = /WX /W4
|
||||
DLLDEF = ../../liblfds611.def
|
||||
TARGETNAME = liblfds611
|
||||
TARGETPATH = ../../bin/
|
||||
TARGETTYPE = EXPORT_DRIVER
|
||||
UMTYPE = nt
|
||||
USER_C_FLAGS = /DWIN_KERNEL_BUILD
|
||||
|
||||
INCLUDES = ..;../../inc/
|
||||
SOURCES = lfds611_abstraction_free.c \
|
||||
lfds611_abstraction_malloc.c \
|
||||
lfds611_freelist_delete.c \
|
||||
lfds611_freelist_get_and_set.c \
|
||||
lfds611_freelist_new.c \
|
||||
lfds611_freelist_pop_push.c \
|
||||
lfds611_freelist_query.c \
|
||||
lfds611_liblfds_abstraction_test_helpers.c \
|
||||
lfds611_liblfds_aligned_free.c \
|
||||
lfds611_liblfds_aligned_malloc.c \
|
||||
lfds611_queue_delete.c \
|
||||
lfds611_queue_new.c \
|
||||
lfds611_queue_query.c \
|
||||
lfds611_queue_queue.c \
|
||||
lfds611_ringbuffer_delete.c \
|
||||
lfds611_ringbuffer_get_and_put.c \
|
||||
lfds611_ringbuffer_new.c \
|
||||
lfds611_ringbuffer_query.c \
|
||||
lfds611_slist_delete.c \
|
||||
lfds611_slist_get_and_set.c \
|
||||
lfds611_slist_link.c \
|
||||
lfds611_slist_new.c \
|
||||
lfds611_stack_delete.c \
|
||||
lfds611_stack_new.c \
|
||||
lfds611_stack_push_pop.c \
|
||||
lfds611_stack_query.c \
|
||||
driver_entry.c
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
MSC_WARNING_LEVEL = /WX /W4
|
||||
TARGETNAME = liblfds611
|
||||
TARGETPATH = ../../bin/
|
||||
TARGETTYPE = DRIVER_LIBRARY
|
||||
UMTYPE = nt
|
||||
USER_C_FLAGS = /DWIN_KERNEL_BUILD
|
||||
|
||||
INCLUDES = ..;../../inc/
|
||||
SOURCES = lfds611_abstraction_free.c \
|
||||
lfds611_abstraction_malloc.c \
|
||||
lfds611_freelist_delete.c \
|
||||
lfds611_freelist_get_and_set.c \
|
||||
lfds611_freelist_new.c \
|
||||
lfds611_freelist_pop_push.c \
|
||||
lfds611_freelist_query.c \
|
||||
lfds611_liblfds_abstraction_test_helpers.c \
|
||||
lfds611_liblfds_aligned_free.c \
|
||||
lfds611_liblfds_aligned_malloc.c \
|
||||
lfds611_queue_delete.c \
|
||||
lfds611_queue_new.c \
|
||||
lfds611_queue_query.c \
|
||||
lfds611_queue_queue.c \
|
||||
lfds611_ringbuffer_delete.c \
|
||||
lfds611_ringbuffer_get_and_put.c \
|
||||
lfds611_ringbuffer_new.c \
|
||||
lfds611_ringbuffer_query.c \
|
||||
lfds611_slist_delete.c \
|
||||
lfds611_slist_get_and_set.c \
|
||||
lfds611_slist_link.c \
|
||||
lfds611_slist_new.c \
|
||||
lfds611_stack_delete.c \
|
||||
lfds611_stack_new.c \
|
||||
lfds611_stack_push_pop.c \
|
||||
lfds611_stack_query.c
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
DIRS = single_dir_for_windows_kernel
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#pragma warning( disable : 4100 )
|
||||
|
||||
NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath )
|
||||
{
|
||||
return( STATUS_SUCCESS );
|
||||
}
|
||||
|
||||
#pragma warning( default : 4100 )
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
This C file (driver_entry.c) is used when building a dynamic library for
|
||||
the Windows kernel. It exists to work around one of the limitations of
|
||||
that build environment. It is not used by any other build; just ignore it.
|
||||
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
#include "lfds611_abstraction_internal_body.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER)
|
||||
|
||||
/* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_cas( volatile lfds611_atom_t *destination, lfds611_atom_t exchange, lfds611_atom_t compare )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv;
|
||||
|
||||
assert( destination != NULL );
|
||||
// TRD : exchange can be any value in its range
|
||||
// TRD : compare can be any value in its range
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
rv = (lfds611_atom_t) _InterlockedCompareExchangePointer( (void * volatile *) destination, (void *) exchange, (void *) compare );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
|
||||
|
||||
/* TRD : any OS on any CPU with GCC 4.1.0 or better
|
||||
|
||||
GCC 4.1.0 introduced the __sync_*() atomic intrinsics
|
||||
|
||||
__GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_cas( volatile lfds611_atom_t *destination, lfds611_atom_t exchange, lfds611_atom_t compare )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv;
|
||||
|
||||
assert( destination != NULL );
|
||||
// TRD : exchange can be any value in its range
|
||||
// TRD : compare can be any value in its range
|
||||
|
||||
// TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
rv = (lfds611_atom_t) __sync_val_compare_and_swap( destination, compare, exchange );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
#include "lfds611_abstraction_internal_body.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN64 && defined _MSC_VER)
|
||||
|
||||
/* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN64 indicates 64 bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
|
||||
{
|
||||
unsigned char
|
||||
cas_result;
|
||||
|
||||
assert( destination != NULL );
|
||||
assert( exchange != NULL );
|
||||
assert( compare != NULL );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( cas_result ) ;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
|
||||
|
||||
/* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
(!defined _WIN64 && defined _WIN32) indicates 32 bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
|
||||
{
|
||||
__int64
|
||||
original_compare;
|
||||
|
||||
assert( destination != NULL );
|
||||
assert( exchange != NULL );
|
||||
assert( compare != NULL );
|
||||
|
||||
*(__int64 *) &original_compare = *(__int64 *) compare;
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
*(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined __x86_64__ && defined __GNUC__)
|
||||
|
||||
/* TRD : any OS on x64 with GCC
|
||||
|
||||
__x86_64__ indicates x64
|
||||
__GNUC__ indicates GCC
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
|
||||
{
|
||||
unsigned char
|
||||
cas_result;
|
||||
|
||||
assert( destination != NULL );
|
||||
assert( exchange != NULL );
|
||||
assert( compare != NULL );
|
||||
|
||||
// TRD : __asm__ with "memory" in the clobber list is for GCC a full compiler barrier
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock;" // make cmpxchg16b atomic
|
||||
"cmpxchg16b %0;" // cmpxchg16b sets ZF on success
|
||||
"setz %3;" // if ZF set, set cas_result to 1
|
||||
|
||||
// output
|
||||
: "+m" (*(volatile lfds611_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
|
||||
|
||||
// input
|
||||
: "b" (*exchange), "c" (*(exchange+1))
|
||||
|
||||
// clobbered
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
return( cas_result );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if ((defined __i686__ || defined __arm__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
|
||||
|
||||
/* TRD : any OS on x86 or ARM with GCC 4.1.0 or better
|
||||
|
||||
GCC 4.1.0 introduced the __sync_*() atomic intrinsics
|
||||
|
||||
__GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
|
||||
{
|
||||
unsigned char
|
||||
cas_result = 0;
|
||||
|
||||
unsigned long long int
|
||||
original_destination;
|
||||
|
||||
assert( destination != NULL );
|
||||
assert( exchange != NULL );
|
||||
assert( compare != NULL );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
original_destination = __sync_val_compare_and_swap( (volatile unsigned long long int *) destination, *(unsigned long long int *) compare, *(unsigned long long int *) exchange );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
if( original_destination == *(unsigned long long int *) compare )
|
||||
cas_result = 1;
|
||||
|
||||
*(unsigned long long int *) compare = original_destination;
|
||||
|
||||
return( cas_result );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
#include "lfds611_abstraction_internal_wrapper.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (!defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any OS except Windows kernel on any CPU with any compiler
|
||||
|
||||
!WIN_KERNEL_BUILD indicates not Windows kernel
|
||||
*/
|
||||
|
||||
void lfds611_abstraction_free( void *memory )
|
||||
{
|
||||
free( memory );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
void lfds611_abstraction_free( void *memory )
|
||||
{
|
||||
ExFreePoolWithTag( memory, 'sdfl' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
#include "lfds611_abstraction_internal_body.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN64 && defined _MSC_VER)
|
||||
|
||||
/* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN64 indicates 64 bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_increment( volatile lfds611_atom_t *value )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv;
|
||||
|
||||
assert( value != NULL );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
rv = (lfds611_atom_t) _InterlockedIncrement64( (__int64 *) value );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
|
||||
|
||||
/* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
(!defined _WIN64 && defined _WIN32) indicates 32 bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_increment( volatile lfds611_atom_t *value )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv;
|
||||
|
||||
assert( value != NULL );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
rv = (lfds611_atom_t) _InterlockedIncrement( (long int *) value );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
|
||||
|
||||
/* TRD : any OS on any CPU with GCC 4.1.0 or better
|
||||
|
||||
GCC 4.1.0 introduced the __sync_*() atomic intrinsics
|
||||
|
||||
__GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
|
||||
*/
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_increment( volatile lfds611_atom_t *value )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv;
|
||||
|
||||
assert( value != NULL );
|
||||
|
||||
// TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
rv = (lfds611_atom_t) __sync_add_and_fetch( value, 1 );
|
||||
|
||||
LFDS611_BARRIER_COMPILER_FULL;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
/***** private prototypes *****/
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** the internal header body *****/
|
||||
#include "lfds611_abstraction_internal_body.h"
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
#include "lfds611_abstraction_internal_wrapper.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (!defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any OS except Windows kernel on any CPU with any compiler
|
||||
|
||||
!WIN_KERNEL_BUILD indicates not Windows kernel
|
||||
*/
|
||||
|
||||
void *lfds611_abstraction_malloc( size_t size )
|
||||
{
|
||||
return( malloc(size) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
|
||||
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
void *lfds611_abstraction_malloc( size_t size )
|
||||
{
|
||||
return( ExAllocatePoolWithTag(NonPagedPool, size, 'sdfl') );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
#include "lfds611_freelist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_freelist_delete( struct lfds611_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
|
||||
assert( fs != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
// TRD : leading load barrier not required as it will be performed by the pop
|
||||
|
||||
while( lfds611_freelist_pop(fs, &fe) ) {
|
||||
if( user_data_delete_function != NULL ) {
|
||||
lfds611_freelist_get_user_data_from_element( fe, &user_data );
|
||||
user_data_delete_function( user_data, user_state );
|
||||
}
|
||||
|
||||
lfds611_liblfds_aligned_free( fe );
|
||||
}
|
||||
|
||||
lfds611_liblfds_aligned_free( fs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
#include "lfds611_freelist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void *lfds611_freelist_get_user_data_from_element( struct lfds611_freelist_element *fe, void **user_data )
|
||||
{
|
||||
assert( fe != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
if( user_data != NULL )
|
||||
*user_data = fe->user_data;
|
||||
|
||||
return( fe->user_data );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_freelist_set_user_data_in_element( struct lfds611_freelist_element *fe, void *user_data )
|
||||
{
|
||||
assert( fe != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
fe->user_data = user_data;
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** defines *****/
|
||||
#define LFDS611_FREELIST_POINTER 0
|
||||
#define LFDS611_FREELIST_COUNTER 1
|
||||
#define LFDS611_FREELIST_PAC_SIZE 2
|
||||
|
||||
/***** structures *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
struct lfds611_freelist_state {
|
||||
struct lfds611_freelist_element
|
||||
*volatile top[LFDS611_FREELIST_PAC_SIZE];
|
||||
|
||||
int
|
||||
(*user_data_init_function)( void **user_data, void *user_state );
|
||||
|
||||
void
|
||||
*user_state;
|
||||
|
||||
lfds611_atom_t
|
||||
aba_counter,
|
||||
element_count;
|
||||
};
|
||||
|
||||
struct lfds611_freelist_element {
|
||||
struct lfds611_freelist_element
|
||||
*next[LFDS611_FREELIST_PAC_SIZE];
|
||||
|
||||
void
|
||||
*user_data;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
/***** private prototypes *****/
|
||||
lfds611_atom_t lfds611_freelist_internal_new_element( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe );
|
||||
void lfds611_freelist_internal_validate( struct lfds611_freelist_state *fs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_freelist_validity );
|
||||
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
#include "lfds611_freelist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_freelist_new( struct lfds611_freelist_state **fs, lfds611_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
lfds611_atom_t
|
||||
element_count;
|
||||
|
||||
assert( fs != NULL );
|
||||
// TRD : number_elements can be any value in its range
|
||||
// TRD : user_data_init_function can be NULL
|
||||
|
||||
*fs = (struct lfds611_freelist_state *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_freelist_state), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( (*fs) != NULL ) {
|
||||
(*fs)->top[LFDS611_FREELIST_POINTER] = NULL;
|
||||
(*fs)->top[LFDS611_FREELIST_COUNTER] = 0;
|
||||
(*fs)->user_data_init_function = user_data_init_function;
|
||||
(*fs)->user_state = user_state;
|
||||
(*fs)->aba_counter = 0;
|
||||
(*fs)->element_count = 0;
|
||||
|
||||
element_count = lfds611_freelist_new_elements( *fs, number_elements );
|
||||
|
||||
if( element_count == number_elements )
|
||||
rv = 1;
|
||||
|
||||
if( element_count != number_elements ) {
|
||||
lfds611_liblfds_aligned_free( (*fs) );
|
||||
*fs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_freelist_use( struct lfds611_freelist_state *fs )
|
||||
{
|
||||
assert( fs != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
lfds611_atom_t lfds611_freelist_new_elements( struct lfds611_freelist_state *fs, lfds611_atom_t number_elements )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
lfds611_atom_t
|
||||
loop,
|
||||
count = 0;
|
||||
|
||||
assert( fs != NULL );
|
||||
// TRD : number_elements can be any value in its range
|
||||
// TRD : user_data_init_function can be NULL
|
||||
|
||||
for( loop = 0 ; loop < number_elements ; loop++ )
|
||||
if( lfds611_freelist_internal_new_element(fs, &fe) ) {
|
||||
lfds611_freelist_push( fs, fe );
|
||||
count++;
|
||||
}
|
||||
|
||||
return( count );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
lfds611_atom_t lfds611_freelist_internal_new_element( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )
|
||||
{
|
||||
lfds611_atom_t
|
||||
rv = 0;
|
||||
|
||||
assert( fs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
/* TRD : basically, does what you'd expect;
|
||||
|
||||
allocates an element
|
||||
calls the user init function
|
||||
if anything fails, cleans up,
|
||||
sets *fe to NULL
|
||||
and returns 0
|
||||
*/
|
||||
|
||||
*fe = (struct lfds611_freelist_element *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_freelist_element), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *fe != NULL ) {
|
||||
if( fs->user_data_init_function == NULL ) {
|
||||
(*fe)->user_data = NULL;
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
if( fs->user_data_init_function != NULL ) {
|
||||
rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state );
|
||||
|
||||
if( rv == 0 ) {
|
||||
lfds611_liblfds_aligned_free( *fe );
|
||||
*fe = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rv == 1 )
|
||||
lfds611_abstraction_increment( (lfds611_atom_t *) &fs->element_count );
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
#include "lfds611_freelist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_freelist_element *lfds611_freelist_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_freelist_element
|
||||
*fe_local[LFDS611_FREELIST_PAC_SIZE];
|
||||
|
||||
assert( fs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
fe_local[LFDS611_FREELIST_COUNTER] = fs->top[LFDS611_FREELIST_COUNTER];
|
||||
fe_local[LFDS611_FREELIST_POINTER] = fs->top[LFDS611_FREELIST_POINTER];
|
||||
|
||||
/* TRD : note that lfds611_abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local)
|
||||
(this happens of course after the CAS itself has occurred inside lfds611_abstraction_dcas)
|
||||
*/
|
||||
|
||||
do {
|
||||
if( fe_local[LFDS611_FREELIST_POINTER] == NULL ) {
|
||||
*fe = NULL;
|
||||
return( *fe );
|
||||
}
|
||||
} while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) fs->top, (lfds611_atom_t *) fe_local[LFDS611_FREELIST_POINTER]->next, (lfds611_atom_t *) fe_local) );
|
||||
|
||||
*fe = (struct lfds611_freelist_element *) fe_local[LFDS611_FREELIST_POINTER];
|
||||
|
||||
return( *fe );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_freelist_element *lfds611_freelist_guaranteed_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )
|
||||
{
|
||||
assert( fs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
lfds611_freelist_internal_new_element( fs, fe );
|
||||
|
||||
return( *fe );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_freelist_push( struct lfds611_freelist_state *fs, struct lfds611_freelist_element *fe )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_freelist_element
|
||||
*fe_local[LFDS611_FREELIST_PAC_SIZE],
|
||||
*original_fe_next[LFDS611_FREELIST_PAC_SIZE];
|
||||
|
||||
assert( fs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
fe_local[LFDS611_FREELIST_POINTER] = fe;
|
||||
fe_local[LFDS611_FREELIST_COUNTER] = (struct lfds611_freelist_element *) lfds611_abstraction_increment( (lfds611_atom_t *) &fs->aba_counter );
|
||||
|
||||
original_fe_next[LFDS611_FREELIST_POINTER] = fs->top[LFDS611_FREELIST_POINTER];
|
||||
original_fe_next[LFDS611_FREELIST_COUNTER] = fs->top[LFDS611_FREELIST_COUNTER];
|
||||
|
||||
/* TRD : note that lfds611_abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next)
|
||||
(this happens of course after the CAS itself has occurred inside lfds611_abstraction_dcas)
|
||||
this then causes us in our loop, should we repeat it, to update fe_local->next to a more
|
||||
up-to-date version of the head of the lfds611_freelist
|
||||
*/
|
||||
|
||||
do {
|
||||
fe_local[LFDS611_FREELIST_POINTER]->next[LFDS611_FREELIST_POINTER] = original_fe_next[LFDS611_FREELIST_POINTER];
|
||||
fe_local[LFDS611_FREELIST_POINTER]->next[LFDS611_FREELIST_COUNTER] = original_fe_next[LFDS611_FREELIST_COUNTER];
|
||||
} while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) fs->top, (lfds611_atom_t *) fe_local, (lfds611_atom_t *) original_fe_next) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
#include "lfds611_freelist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_freelist_query( struct lfds611_freelist_state *fs, enum lfds611_freelist_query_type query_type, void *query_input, void *query_output )
|
||||
{
|
||||
assert( fs != NULL );
|
||||
// TRD : query type can be any value in its range
|
||||
// TRD : query_input can be NULL in some cases
|
||||
assert( query_output != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
switch( query_type ) {
|
||||
case LFDS611_FREELIST_QUERY_ELEMENT_COUNT:
|
||||
assert( query_input == NULL );
|
||||
|
||||
*(lfds611_atom_t *) query_output = fs->element_count;
|
||||
break;
|
||||
|
||||
case LFDS611_FREELIST_QUERY_VALIDATE:
|
||||
// TRD : query_input can be NULL
|
||||
|
||||
lfds611_freelist_internal_validate( fs, (struct lfds611_validation_info *) query_input, (enum lfds611_data_structure_validity *) query_output );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_freelist_internal_validate( struct lfds611_freelist_state *fs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_freelist_validity )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe,
|
||||
*fe_slow,
|
||||
*fe_fast;
|
||||
|
||||
lfds611_atom_t
|
||||
element_count = 0;
|
||||
|
||||
assert( fs != NULL );
|
||||
// TRD : vi can be NULL
|
||||
assert( lfds611_freelist_validity != NULL );
|
||||
|
||||
*lfds611_freelist_validity = LFDS611_VALIDITY_VALID;
|
||||
|
||||
fe_slow = fe_fast = (struct lfds611_freelist_element *) fs->top[LFDS611_FREELIST_POINTER];
|
||||
|
||||
/* TRD : first, check for a loop
|
||||
we have two pointers
|
||||
both of which start at the top of the lfds611_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 lfds611_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[LFDS611_FREELIST_POINTER];
|
||||
|
||||
if( fe_fast != NULL )
|
||||
fe_fast = fe_fast->next[LFDS611_FREELIST_POINTER];
|
||||
|
||||
if( fe_fast != NULL )
|
||||
fe_fast = fe_fast->next[LFDS611_FREELIST_POINTER];
|
||||
} while( fe_slow != NULL and fe_fast != fe_slow );
|
||||
|
||||
if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
|
||||
*lfds611_freelist_validity = LFDS611_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( *lfds611_freelist_validity == LFDS611_VALIDITY_VALID and vi != NULL ) {
|
||||
fe = (struct lfds611_freelist_element *) fs->top[LFDS611_FREELIST_POINTER];
|
||||
|
||||
while( fe != NULL ) {
|
||||
element_count++;
|
||||
fe = (struct lfds611_freelist_element *) fe->next[LFDS611_FREELIST_POINTER];
|
||||
}
|
||||
|
||||
if( element_count < vi->min_elements )
|
||||
*lfds611_freelist_validity = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( element_count > vi->max_elements )
|
||||
*lfds611_freelist_validity = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
#include "lfds611_liblfds_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_liblfds_abstraction_test_helper_increment_non_atomic( lfds611_atom_t *shared_counter )
|
||||
{
|
||||
/* TRD : lfds611_atom_t must be volatile or the compiler
|
||||
optimizes it away into a single store
|
||||
*/
|
||||
|
||||
volatile lfds611_atom_t
|
||||
count = 0;
|
||||
|
||||
assert( shared_counter != NULL );
|
||||
|
||||
while( count++ < 10000000 )
|
||||
(*(lfds611_atom_t *) shared_counter)++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_liblfds_abstraction_test_helper_increment_atomic( volatile lfds611_atom_t *shared_counter )
|
||||
{
|
||||
lfds611_atom_t
|
||||
count = 0;
|
||||
|
||||
assert( shared_counter != NULL );
|
||||
|
||||
while( count++ < 10000000 )
|
||||
lfds611_abstraction_increment( shared_counter );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_liblfds_abstraction_test_helper_cas( volatile lfds611_atom_t *shared_counter, lfds611_atom_t *local_counter )
|
||||
{
|
||||
lfds611_atom_t
|
||||
loop = 0,
|
||||
original_destination;
|
||||
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) lfds611_atom_t
|
||||
exchange,
|
||||
compare;
|
||||
|
||||
assert( shared_counter != NULL );
|
||||
assert( local_counter != NULL );
|
||||
|
||||
while( loop++ < 1000000 ) {
|
||||
do {
|
||||
compare = *shared_counter;
|
||||
exchange = compare + 1;
|
||||
|
||||
original_destination = lfds611_abstraction_cas( shared_counter, exchange, compare );
|
||||
} while( original_destination != compare );
|
||||
|
||||
(*local_counter)++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_liblfds_abstraction_test_helper_dcas( volatile lfds611_atom_t *shared_counter, lfds611_atom_t *local_counter )
|
||||
{
|
||||
lfds611_atom_t
|
||||
loop = 0;
|
||||
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) lfds611_atom_t
|
||||
exchange[2],
|
||||
compare[2];
|
||||
|
||||
assert( shared_counter != NULL );
|
||||
assert( local_counter != NULL );
|
||||
|
||||
while( loop++ < 1000000 ) {
|
||||
compare[0] = *shared_counter;
|
||||
compare[1] = *(shared_counter+1);
|
||||
|
||||
do {
|
||||
exchange[0] = compare[0] + 1;
|
||||
exchange[1] = compare[1];
|
||||
} while( 0 == lfds611_abstraction_dcas(shared_counter, exchange, compare) );
|
||||
|
||||
(*local_counter)++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
#include "lfds611_liblfds_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_liblfds_aligned_free( void *memory )
|
||||
{
|
||||
assert( memory != NULL );
|
||||
|
||||
// TRD : the "void *" stored above memory points to the root of the allocation
|
||||
lfds611_abstraction_free( *( (void **) memory - 1 ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
#include "lfds611_liblfds_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void *lfds611_liblfds_aligned_malloc( size_t size, size_t align_in_bytes )
|
||||
{
|
||||
void
|
||||
*original_memory,
|
||||
*memory;
|
||||
|
||||
size_t
|
||||
offset;
|
||||
|
||||
// TRD : size can be any value in its range
|
||||
// TRD : align_in_bytes can be any value in its range
|
||||
|
||||
original_memory = memory = lfds611_abstraction_malloc( size + sizeof(void *) + align_in_bytes );
|
||||
|
||||
if( memory != NULL ) {
|
||||
memory = (void **) memory + 1;
|
||||
offset = align_in_bytes - (size_t) memory % align_in_bytes;
|
||||
memory = (unsigned char *) memory + offset;
|
||||
*( (void **) memory - 1 ) = original_memory;
|
||||
}
|
||||
|
||||
return( memory );
|
||||
}
|
||||
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
This is not a data structure but rather functions internal to the library.
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "lfds611_queue_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_delete( struct lfds611_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
void
|
||||
*user_data;
|
||||
|
||||
assert( qs != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
// TRD : leading load barrier not required as it will be performed by the dequeue
|
||||
|
||||
while( lfds611_queue_dequeue(qs, &user_data) )
|
||||
if( user_data_delete_function != NULL )
|
||||
user_data_delete_function( user_data, user_state );
|
||||
|
||||
/* TRD : fully dequeuing will leave us
|
||||
with a single dummy element
|
||||
which both qs->enqueue and qs->dequeue point at
|
||||
we push this back onto the lfds611_freelist
|
||||
before we delete the lfds611_freelist
|
||||
*/
|
||||
|
||||
lfds611_freelist_push( qs->fs, qs->enqueue[LFDS611_QUEUE_POINTER]->fe );
|
||||
|
||||
lfds611_freelist_delete( qs->fs, lfds611_queue_internal_freelist_delete_function, NULL );
|
||||
|
||||
lfds611_liblfds_aligned_free( qs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_queue_internal_freelist_delete_function( void *user_data, void *user_state )
|
||||
{
|
||||
assert( user_data != NULL );
|
||||
assert( user_state == NULL );
|
||||
|
||||
lfds611_liblfds_aligned_free( user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** pragmas *****/
|
||||
|
||||
/***** defines *****/
|
||||
#define LFDS611_QUEUE_STATE_UNKNOWN -1
|
||||
#define LFDS611_QUEUE_STATE_EMPTY 0
|
||||
#define LFDS611_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE 1
|
||||
#define LFDS611_QUEUE_STATE_ATTEMPT_DELFDS611_QUEUE 2
|
||||
|
||||
#define LFDS611_QUEUE_POINTER 0
|
||||
#define LFDS611_QUEUE_COUNTER 1
|
||||
#define LFDS611_QUEUE_PAC_SIZE 2
|
||||
|
||||
/***** structures *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
struct lfds611_queue_state {
|
||||
struct lfds611_queue_element
|
||||
*volatile enqueue[LFDS611_QUEUE_PAC_SIZE],
|
||||
*volatile dequeue[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
lfds611_atom_t
|
||||
aba_counter;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
};
|
||||
|
||||
struct lfds611_queue_element {
|
||||
// TRD : next in a lfds611_queue requires volatile as it is target of CAS
|
||||
struct lfds611_queue_element
|
||||
*volatile next[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
/***** externs *****/
|
||||
|
||||
/***** private prototypes *****/
|
||||
int lfds611_queue_internal_freelist_init_function( void **user_data, void *user_state );
|
||||
void lfds611_queue_internal_freelist_delete_function( void *user_data, void *user_state );
|
||||
|
||||
void lfds611_queue_internal_new_element_from_freelist( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE], void *user_data );
|
||||
void lfds611_queue_internal_guaranteed_new_element_from_freelist( struct lfds611_queue_state *qs, struct lfds611_queue_element * qe[LFDS611_QUEUE_PAC_SIZE], void *user_data );
|
||||
void lfds611_queue_internal_init_element( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE], struct lfds611_freelist_element *fe, void *user_data );
|
||||
|
||||
void lfds611_queue_internal_queue( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE] );
|
||||
|
||||
void lfds611_queue_internal_validate( struct lfds611_queue_state *qs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_queue_validity,
|
||||
enum lfds611_data_structure_validity *lfds611_freelist_validity );
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
#include "lfds611_queue_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_queue_new( struct lfds611_queue_state **qs, lfds611_atom_t number_elements )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
struct lfds611_queue_element
|
||||
*qe[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
assert( qs != NULL );
|
||||
// TRD : number_elements can be any value in its range
|
||||
|
||||
*qs = (struct lfds611_queue_state *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_queue_state), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *qs != NULL ) {
|
||||
// TRD : the size of the lfds611_freelist is the size of the lfds611_queue (+1 for the leading dummy element, which is hidden from the caller)
|
||||
lfds611_freelist_new( &(*qs)->fs, number_elements+1, lfds611_queue_internal_freelist_init_function, NULL );
|
||||
|
||||
if( (*qs)->fs != NULL ) {
|
||||
lfds611_queue_internal_new_element_from_freelist( *qs, qe, NULL );
|
||||
(*qs)->enqueue[LFDS611_QUEUE_POINTER] = (*qs)->dequeue[LFDS611_QUEUE_POINTER] = qe[LFDS611_QUEUE_POINTER];
|
||||
(*qs)->enqueue[LFDS611_QUEUE_COUNTER] = (*qs)->dequeue[LFDS611_QUEUE_COUNTER] = 0;
|
||||
(*qs)->aba_counter = 0;
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
if( (*qs)->fs == NULL ) {
|
||||
lfds611_liblfds_aligned_free( *qs );
|
||||
*qs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_queue_use( struct lfds611_queue_state *qs )
|
||||
{
|
||||
assert( qs != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
int lfds611_queue_internal_freelist_init_function( void **user_data, void *user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
assert( user_data != NULL );
|
||||
assert( user_state == NULL );
|
||||
|
||||
*user_data = lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_queue_element), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *user_data != NULL )
|
||||
rv = 1;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_internal_new_element_from_freelist( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE], void *user_data )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( qs != NULL );
|
||||
assert( qe != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
qe[LFDS611_QUEUE_POINTER] = NULL;
|
||||
|
||||
lfds611_freelist_pop( qs->fs, &fe );
|
||||
|
||||
if( fe != NULL )
|
||||
lfds611_queue_internal_init_element( qs, qe, fe, user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_internal_guaranteed_new_element_from_freelist( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE], void *user_data )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( qs != NULL );
|
||||
assert( qe != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
qe[LFDS611_QUEUE_POINTER] = NULL;
|
||||
|
||||
lfds611_freelist_guaranteed_pop( qs->fs, &fe );
|
||||
|
||||
if( fe != NULL )
|
||||
lfds611_queue_internal_init_element( qs, qe, fe, user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_internal_init_element( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE], struct lfds611_freelist_element *fe, void *user_data )
|
||||
{
|
||||
assert( qs != NULL );
|
||||
assert( qe != NULL );
|
||||
assert( fe != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &qe[LFDS611_QUEUE_POINTER] );
|
||||
qe[LFDS611_QUEUE_COUNTER] = (struct lfds611_queue_element *) lfds611_abstraction_increment( (lfds611_atom_t *) &qs->aba_counter );
|
||||
|
||||
qe[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_POINTER] = NULL;
|
||||
qe[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_COUNTER] = (struct lfds611_queue_element *) lfds611_abstraction_increment( (lfds611_atom_t *) &qs->aba_counter );
|
||||
|
||||
qe[LFDS611_QUEUE_POINTER]->fe = fe;
|
||||
qe[LFDS611_QUEUE_POINTER]->user_data = user_data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
#include "lfds611_queue_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_queue_query( struct lfds611_queue_state *qs, enum lfds611_queue_query_type query_type, void *query_input, void *query_output )
|
||||
{
|
||||
assert( qs != NULL );
|
||||
// TRD : query_type can be any value in its range
|
||||
// TRD : query_input can be NULL
|
||||
assert( query_output != NULL );
|
||||
|
||||
switch( query_type ) {
|
||||
case LFDS611_QUEUE_QUERY_ELEMENT_COUNT:
|
||||
assert( query_input == NULL );
|
||||
|
||||
lfds611_freelist_query( qs->fs, LFDS611_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
|
||||
break;
|
||||
|
||||
case LFDS611_QUEUE_QUERY_VALIDATE:
|
||||
// TRD : query_input can be NULL
|
||||
|
||||
lfds611_queue_internal_validate( qs, (struct lfds611_validation_info *) query_input, (enum lfds611_data_structure_validity *) query_output, ((enum lfds611_data_structure_validity *) query_output)+1 );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_internal_validate( struct lfds611_queue_state *qs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_queue_validity,
|
||||
enum lfds611_data_structure_validity *lfds611_freelist_validity )
|
||||
{
|
||||
struct lfds611_queue_element
|
||||
*qe,
|
||||
*qe_slow,
|
||||
*qe_fast;
|
||||
|
||||
lfds611_atom_t
|
||||
element_count = 0,
|
||||
total_elements;
|
||||
|
||||
struct lfds611_validation_info
|
||||
lfds611_freelist_vi;
|
||||
|
||||
assert( qs != NULL );
|
||||
// TRD : vi can be NULL
|
||||
assert( lfds611_queue_validity != NULL );
|
||||
assert( lfds611_freelist_validity != NULL );
|
||||
|
||||
*lfds611_queue_validity = LFDS611_VALIDITY_VALID;
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
qe_slow = qe_fast = (struct lfds611_queue_element *) qs->dequeue[LFDS611_QUEUE_POINTER];
|
||||
|
||||
/* TRD : first, check for a loop
|
||||
we have two pointers
|
||||
both of which start at the dequeue end of the lfds611_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 lfds611_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[LFDS611_QUEUE_POINTER];
|
||||
|
||||
if( qe_fast != NULL )
|
||||
qe_fast = qe_fast->next[LFDS611_QUEUE_POINTER];
|
||||
|
||||
if( qe_fast != NULL )
|
||||
qe_fast = qe_fast->next[LFDS611_QUEUE_POINTER];
|
||||
} while( qe_slow != NULL and qe_fast != qe_slow );
|
||||
|
||||
if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
|
||||
*lfds611_queue_validity = LFDS611_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( *lfds611_queue_validity == LFDS611_VALIDITY_VALID and vi != NULL ) {
|
||||
qe = (struct lfds611_queue_element *) qs->dequeue[LFDS611_QUEUE_POINTER];
|
||||
|
||||
while( qe != NULL ) {
|
||||
element_count++;
|
||||
qe = (struct lfds611_queue_element *) qe->next[LFDS611_QUEUE_POINTER];
|
||||
}
|
||||
|
||||
/* TRD : remember there is a dummy element in the lfds611_queue */
|
||||
element_count--;
|
||||
|
||||
if( element_count < vi->min_elements )
|
||||
*lfds611_queue_validity = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( element_count > vi->max_elements )
|
||||
*lfds611_queue_validity = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
}
|
||||
|
||||
/* TRD : now we validate the lfds611_freelist
|
||||
|
||||
we may be able to check for the expected number of
|
||||
elements in the lfds611_freelist
|
||||
|
||||
if the caller has given us an expected min and max
|
||||
number of elements in the lfds611_queue, then the total number
|
||||
of elements in the lfds611_freelist, minus that min and max,
|
||||
gives us the expected number of elements in the
|
||||
lfds611_freelist
|
||||
*/
|
||||
|
||||
if( vi != NULL ) {
|
||||
lfds611_freelist_query( qs->fs, LFDS611_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
|
||||
|
||||
/* TRD : remember there is a dummy element in the lfds611_queue */
|
||||
total_elements--;
|
||||
|
||||
lfds611_freelist_vi.min_elements = total_elements - vi->max_elements;
|
||||
lfds611_freelist_vi.max_elements = total_elements - vi->min_elements;
|
||||
|
||||
lfds611_freelist_query( qs->fs, LFDS611_FREELIST_QUERY_VALIDATE, (void *) &lfds611_freelist_vi, (void *) lfds611_freelist_validity );
|
||||
}
|
||||
|
||||
if( vi == NULL )
|
||||
lfds611_freelist_query( qs->fs, LFDS611_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds611_freelist_validity );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
#include "lfds611_queue_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_queue_enqueue( struct lfds611_queue_state *qs, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_queue_element
|
||||
*qe[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
assert( qs != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
lfds611_queue_internal_new_element_from_freelist( qs, qe, user_data );
|
||||
|
||||
if( qe[LFDS611_QUEUE_POINTER] == NULL )
|
||||
return( 0 );
|
||||
|
||||
lfds611_queue_internal_queue( qs, qe );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_queue_guaranteed_enqueue( struct lfds611_queue_state *qs, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_queue_element
|
||||
*qe[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
assert( qs != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
lfds611_queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data );
|
||||
|
||||
if( qe[LFDS611_QUEUE_POINTER] == NULL )
|
||||
return( 0 );
|
||||
|
||||
lfds611_queue_internal_queue( qs, qe );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_queue_internal_queue( struct lfds611_queue_state *qs, struct lfds611_queue_element *qe[LFDS611_QUEUE_PAC_SIZE] )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_queue_element
|
||||
*enqueue[LFDS611_QUEUE_PAC_SIZE],
|
||||
*next[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
unsigned char
|
||||
cas_result = 0;
|
||||
|
||||
assert( qs != NULL );
|
||||
assert( qe != NULL );
|
||||
|
||||
// TRD : the DCAS operation issues a read and write barrier, so we don't need a read barrier in the do() loop
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
do {
|
||||
enqueue[LFDS611_QUEUE_POINTER] = qs->enqueue[LFDS611_QUEUE_POINTER];
|
||||
enqueue[LFDS611_QUEUE_COUNTER] = qs->enqueue[LFDS611_QUEUE_COUNTER];
|
||||
|
||||
next[LFDS611_QUEUE_POINTER] = enqueue[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_POINTER];
|
||||
next[LFDS611_QUEUE_COUNTER] = enqueue[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_COUNTER];
|
||||
|
||||
/* TRD : this if() ensures that the next we read, just above,
|
||||
really is from qs->enqueue (which we copied into enqueue)
|
||||
*/
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
if( qs->enqueue[LFDS611_QUEUE_POINTER] == enqueue[LFDS611_QUEUE_POINTER] and qs->enqueue[LFDS611_QUEUE_COUNTER] == enqueue[LFDS611_QUEUE_COUNTER] ) {
|
||||
if( next[LFDS611_QUEUE_POINTER] == NULL ) {
|
||||
qe[LFDS611_QUEUE_COUNTER] = next[LFDS611_QUEUE_COUNTER] + 1;
|
||||
cas_result = lfds611_abstraction_dcas( (volatile lfds611_atom_t *) enqueue[LFDS611_QUEUE_POINTER]->next, (lfds611_atom_t *) qe, (lfds611_atom_t *) next );
|
||||
} else {
|
||||
next[LFDS611_QUEUE_COUNTER] = enqueue[LFDS611_QUEUE_COUNTER] + 1;
|
||||
lfds611_abstraction_dcas( (volatile lfds611_atom_t *) qs->enqueue, (lfds611_atom_t *) next, (lfds611_atom_t *) enqueue );
|
||||
}
|
||||
}
|
||||
} while( cas_result == 0 );
|
||||
|
||||
qe[LFDS611_QUEUE_COUNTER] = enqueue[LFDS611_QUEUE_COUNTER] + 1;
|
||||
lfds611_abstraction_dcas( (volatile lfds611_atom_t *) qs->enqueue, (lfds611_atom_t *) qe, (lfds611_atom_t *) enqueue );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_queue_dequeue( struct lfds611_queue_state *qs, void **user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_queue_element
|
||||
*enqueue[LFDS611_QUEUE_PAC_SIZE],
|
||||
*dequeue[LFDS611_QUEUE_PAC_SIZE],
|
||||
*next[LFDS611_QUEUE_PAC_SIZE];
|
||||
|
||||
unsigned char
|
||||
cas_result = 0;
|
||||
|
||||
int
|
||||
rv = 1,
|
||||
state = LFDS611_QUEUE_STATE_UNKNOWN,
|
||||
finished_flag = LOWERED;
|
||||
|
||||
assert( qs != NULL );
|
||||
assert( user_data != NULL );
|
||||
|
||||
// TRD : the DCAS operation issues a read and write barrier, so we don't need a read barrier in the do() loop
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
do {
|
||||
dequeue[LFDS611_QUEUE_POINTER] = qs->dequeue[LFDS611_QUEUE_POINTER];
|
||||
dequeue[LFDS611_QUEUE_COUNTER] = qs->dequeue[LFDS611_QUEUE_COUNTER];
|
||||
|
||||
enqueue[LFDS611_QUEUE_POINTER] = qs->enqueue[LFDS611_QUEUE_POINTER];
|
||||
enqueue[LFDS611_QUEUE_COUNTER] = qs->enqueue[LFDS611_QUEUE_COUNTER];
|
||||
|
||||
next[LFDS611_QUEUE_POINTER] = dequeue[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_POINTER];
|
||||
next[LFDS611_QUEUE_COUNTER] = dequeue[LFDS611_QUEUE_POINTER]->next[LFDS611_QUEUE_COUNTER];
|
||||
|
||||
/* TRD : confirm that dequeue didn't move between reading it
|
||||
and reading its next pointer
|
||||
*/
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
if( dequeue[LFDS611_QUEUE_POINTER] == qs->dequeue[LFDS611_QUEUE_POINTER] and dequeue[LFDS611_QUEUE_COUNTER] == qs->dequeue[LFDS611_QUEUE_COUNTER] ) {
|
||||
if( enqueue[LFDS611_QUEUE_POINTER] == dequeue[LFDS611_QUEUE_POINTER] and next[LFDS611_QUEUE_POINTER] == NULL )
|
||||
state = LFDS611_QUEUE_STATE_EMPTY;
|
||||
|
||||
if( enqueue[LFDS611_QUEUE_POINTER] == dequeue[LFDS611_QUEUE_POINTER] and next[LFDS611_QUEUE_POINTER] != NULL )
|
||||
state = LFDS611_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
|
||||
|
||||
if( enqueue[LFDS611_QUEUE_POINTER] != dequeue[LFDS611_QUEUE_POINTER] )
|
||||
state = LFDS611_QUEUE_STATE_ATTEMPT_DELFDS611_QUEUE;
|
||||
|
||||
switch( state ) {
|
||||
case LFDS611_QUEUE_STATE_EMPTY:
|
||||
*user_data = NULL;
|
||||
rv = 0;
|
||||
finished_flag = RAISED;
|
||||
break;
|
||||
|
||||
case LFDS611_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
|
||||
next[LFDS611_QUEUE_COUNTER] = enqueue[LFDS611_QUEUE_COUNTER] + 1;
|
||||
lfds611_abstraction_dcas( (volatile lfds611_atom_t *) qs->enqueue, (lfds611_atom_t *) next, (lfds611_atom_t *) enqueue );
|
||||
break;
|
||||
|
||||
case LFDS611_QUEUE_STATE_ATTEMPT_DELFDS611_QUEUE:
|
||||
*user_data = next[LFDS611_QUEUE_POINTER]->user_data;
|
||||
|
||||
next[LFDS611_QUEUE_COUNTER] = dequeue[LFDS611_QUEUE_COUNTER] + 1;
|
||||
cas_result = lfds611_abstraction_dcas( (volatile lfds611_atom_t *) qs->dequeue, (lfds611_atom_t *) next, (lfds611_atom_t *) dequeue );
|
||||
|
||||
if( cas_result == 1 )
|
||||
finished_flag = RAISED;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while( finished_flag == LOWERED );
|
||||
|
||||
if( cas_result == 1 )
|
||||
lfds611_freelist_push( qs->fs, dequeue[LFDS611_QUEUE_POINTER]->fe );
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
#include "lfds611_ringbuffer_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_ringbuffer_delete( struct lfds611_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
lfds611_queue_delete( rs->qs, NULL, NULL );
|
||||
|
||||
lfds611_freelist_delete( rs->fs, user_data_delete_function, user_state );
|
||||
|
||||
lfds611_liblfds_aligned_free( rs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
#include "lfds611_ringbuffer_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_freelist_element *lfds611_ringbuffer_get_read_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element **fe )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
lfds611_queue_dequeue( rs->qs, (void **) fe );
|
||||
|
||||
return( *fe );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_freelist_element *lfds611_ringbuffer_get_write_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element **fe, int *overwrite_flag )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
assert( fe != NULL );
|
||||
// TRD : overwrite_flag can be NULL
|
||||
|
||||
/* TRD : we try to obtain an element from the lfds611_freelist
|
||||
if we can, we populate it and add it to the lfds611_queue
|
||||
|
||||
if we cannot, then the lfds611_ringbuffer is full
|
||||
so instead we grab the current read element and
|
||||
use that instead
|
||||
|
||||
dequeue may fail since the lfds611_queue may be emptied
|
||||
during our dequeue attempt
|
||||
|
||||
so what we actually do here is a loop, attempting
|
||||
the lfds611_freelist and if it fails then a dequeue, until
|
||||
we obtain an element
|
||||
|
||||
once we have an element, we lfds611_queue it
|
||||
|
||||
you may be wondering why this operation is in a loop
|
||||
remember - these operations are lock-free; anything
|
||||
can happen in between
|
||||
|
||||
so for example the pop could fail because the lfds611_freelist
|
||||
is empty; but by the time we go to get an element from
|
||||
the lfds611_queue, the whole lfds611_queue has been emptied back into
|
||||
the lfds611_freelist!
|
||||
|
||||
if overwrite_flag is provided, we set it to 0 if we
|
||||
obtained a new element from the lfds611_freelist, 1 if we
|
||||
stole an element from the lfds611_queue
|
||||
*/
|
||||
|
||||
do {
|
||||
if( overwrite_flag != NULL )
|
||||
*overwrite_flag = 0;
|
||||
|
||||
lfds611_freelist_pop( rs->fs, fe );
|
||||
|
||||
if( *fe == NULL ) {
|
||||
lfds611_ringbuffer_get_read_element( rs, fe );
|
||||
|
||||
if( overwrite_flag != NULL and *fe != NULL )
|
||||
*overwrite_flag = 1;
|
||||
}
|
||||
} while( *fe == NULL );
|
||||
|
||||
return( *fe );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_ringbuffer_put_read_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element *fe )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
lfds611_freelist_push( rs->fs, fe );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_ringbuffer_put_write_element( struct lfds611_ringbuffer_state *rs, struct lfds611_freelist_element *fe )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
assert( fe != NULL );
|
||||
|
||||
lfds611_queue_enqueue( rs->qs, fe );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** defines *****/
|
||||
|
||||
/***** structures *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
struct lfds611_ringbuffer_state {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
/***** externs *****/
|
||||
|
||||
/***** private prototypes *****/
|
||||
void lfds611_ringbuffer_internal_validate( struct lfds611_ringbuffer_state *rs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_queue_validity,
|
||||
enum lfds611_data_structure_validity *lfds611_freelist_validity );
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
#include "lfds611_ringbuffer_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_ringbuffer_new( struct lfds611_ringbuffer_state **rs, lfds611_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
assert( rs != NULL );
|
||||
// TRD : number_elements can be any value in its range
|
||||
// TRD : user_data_init_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
*rs = (struct lfds611_ringbuffer_state *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_ringbuffer_state), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *rs != NULL ) {
|
||||
lfds611_freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state );
|
||||
|
||||
if( (*rs)->fs != NULL ) {
|
||||
lfds611_queue_new( &(*rs)->qs, number_elements );
|
||||
|
||||
if( (*rs)->qs != NULL )
|
||||
rv = 1;
|
||||
|
||||
if( (*rs)->qs == NULL ) {
|
||||
lfds611_liblfds_aligned_free( *rs );
|
||||
*rs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( (*rs)->fs == NULL ) {
|
||||
lfds611_liblfds_aligned_free( *rs );
|
||||
*rs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_ringbuffer_use( struct lfds611_ringbuffer_state *rs )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
#include "lfds611_ringbuffer_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_ringbuffer_query( struct lfds611_ringbuffer_state *rs, enum lfds611_ringbuffer_query_type query_type, void *query_input, void *query_output )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
// TRD : query_type can be any value in its range
|
||||
// TRD : query_input can be NULL
|
||||
assert( query_output != NULL );
|
||||
|
||||
switch( query_type ) {
|
||||
case LFDS611_RINGBUFFER_QUERY_VALIDATE:
|
||||
// TRD : query_input can be NULL
|
||||
|
||||
lfds611_ringbuffer_internal_validate( rs, (struct lfds611_validation_info *) query_input, (enum lfds611_data_structure_validity *) query_output,
|
||||
((enum lfds611_data_structure_validity *) query_output)+2 );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_ringbuffer_internal_validate( struct lfds611_ringbuffer_state *rs, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *lfds611_queue_validity,
|
||||
enum lfds611_data_structure_validity *lfds611_freelist_validity )
|
||||
{
|
||||
assert( rs != NULL );
|
||||
// TRD : vi can be NULL
|
||||
assert( lfds611_queue_validity != NULL );
|
||||
assert( lfds611_freelist_validity != NULL );
|
||||
|
||||
lfds611_queue_query( rs->qs, LFDS611_QUEUE_QUERY_VALIDATE, vi, lfds611_queue_validity );
|
||||
|
||||
if( vi != NULL ) {
|
||||
struct lfds611_validation_info
|
||||
lfds611_freelist_vi;
|
||||
|
||||
lfds611_atom_t
|
||||
total_elements;
|
||||
|
||||
lfds611_freelist_query( rs->fs, LFDS611_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
|
||||
lfds611_freelist_vi.min_elements = total_elements - vi->max_elements;
|
||||
lfds611_freelist_vi.max_elements = total_elements - vi->min_elements;
|
||||
lfds611_freelist_query( rs->fs, LFDS611_FREELIST_QUERY_VALIDATE, (void *) &lfds611_freelist_vi, (void *) lfds611_freelist_validity );
|
||||
}
|
||||
|
||||
if( vi == NULL )
|
||||
lfds611_freelist_query( rs->fs, LFDS611_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds611_freelist_validity );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
#include "lfds611_slist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_delete( struct lfds611_slist_state *ss )
|
||||
{
|
||||
lfds611_slist_single_threaded_physically_delete_all_elements( ss );
|
||||
|
||||
lfds611_liblfds_aligned_free( ss );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_slist_logically_delete_element( struct lfds611_slist_state *ss, struct lfds611_slist_element *se )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) void
|
||||
*volatile user_data_and_flags[2],
|
||||
*volatile new_user_data_and_flags[2];
|
||||
|
||||
unsigned char
|
||||
cas_rv = 0;
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
user_data_and_flags[LFDS611_SLIST_USER_DATA] = se->user_data_and_flags[LFDS611_SLIST_USER_DATA];
|
||||
user_data_and_flags[LFDS611_SLIST_FLAGS] = se->user_data_and_flags[LFDS611_SLIST_FLAGS];
|
||||
|
||||
do {
|
||||
new_user_data_and_flags[LFDS611_SLIST_USER_DATA] = user_data_and_flags[LFDS611_SLIST_USER_DATA];
|
||||
new_user_data_and_flags[LFDS611_SLIST_FLAGS] = (void *) ((lfds611_atom_t) user_data_and_flags[LFDS611_SLIST_FLAGS] | LFDS611_SLIST_FLAG_DELETED);
|
||||
} while( !((lfds611_atom_t) user_data_and_flags[LFDS611_SLIST_FLAGS] & LFDS611_SLIST_FLAG_DELETED)
|
||||
and 0 == (cas_rv = lfds611_abstraction_dcas((volatile lfds611_atom_t *) se->user_data_and_flags, (lfds611_atom_t *) new_user_data_and_flags, (lfds611_atom_t *) user_data_and_flags)) );
|
||||
|
||||
if( cas_rv == 1 )
|
||||
if( ss->user_data_delete_function != NULL )
|
||||
ss->user_data_delete_function( (void *) user_data_and_flags[LFDS611_SLIST_USER_DATA], ss->user_state );
|
||||
|
||||
return( cas_rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_single_threaded_physically_delete_all_elements( struct lfds611_slist_state *ss )
|
||||
{
|
||||
struct lfds611_slist_element
|
||||
*volatile se,
|
||||
*volatile se_temp;
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
se = ss->head;
|
||||
|
||||
while( se != NULL ) {
|
||||
// TRD : if a non-deleted element and there is a delete function, call the delete function
|
||||
if( ss->user_data_delete_function != NULL )
|
||||
ss->user_data_delete_function( (void *) se->user_data_and_flags[LFDS611_SLIST_USER_DATA], ss->user_state );
|
||||
|
||||
se_temp = se;
|
||||
se = se->next;
|
||||
lfds611_liblfds_aligned_free( (void *) se_temp );
|
||||
}
|
||||
|
||||
lfds611_slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state );
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
#include "lfds611_slist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_slist_get_user_data_from_element( struct lfds611_slist_element *se, void **user_data )
|
||||
{
|
||||
int
|
||||
rv = 1;
|
||||
|
||||
assert( se != NULL );
|
||||
assert( user_data != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
*user_data = (void *) se->user_data_and_flags[LFDS611_SLIST_USER_DATA];
|
||||
|
||||
if( (lfds611_atom_t) se->user_data_and_flags[LFDS611_SLIST_FLAGS] & LFDS611_SLIST_FLAG_DELETED )
|
||||
rv = 0;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_slist_set_user_data_in_element( struct lfds611_slist_element *se, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) void
|
||||
*user_data_and_flags[2],
|
||||
*new_user_data_and_flags[2];
|
||||
|
||||
int
|
||||
rv = 1;
|
||||
|
||||
assert( se != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
user_data_and_flags[LFDS611_SLIST_USER_DATA] = se->user_data_and_flags[LFDS611_SLIST_USER_DATA];
|
||||
user_data_and_flags[LFDS611_SLIST_FLAGS] = se->user_data_and_flags[LFDS611_SLIST_FLAGS];
|
||||
|
||||
new_user_data_and_flags[LFDS611_SLIST_USER_DATA] = user_data;
|
||||
|
||||
do {
|
||||
new_user_data_and_flags[LFDS611_SLIST_FLAGS] = user_data_and_flags[LFDS611_SLIST_FLAGS];
|
||||
} while( !((lfds611_atom_t) user_data_and_flags[LFDS611_SLIST_FLAGS] & LFDS611_SLIST_FLAG_DELETED) and
|
||||
0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) se->user_data_and_flags, (lfds611_atom_t *) new_user_data_and_flags, (lfds611_atom_t *) user_data_and_flags) );
|
||||
|
||||
if( (lfds611_atom_t) user_data_and_flags[LFDS611_SLIST_FLAGS] & LFDS611_SLIST_FLAG_DELETED )
|
||||
rv = 0;
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_slist_element *lfds611_slist_get_head( struct lfds611_slist_state *ss, struct lfds611_slist_element **se )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
*se = (struct lfds611_slist_element *) ss->head;
|
||||
|
||||
lfds611_slist_internal_move_to_first_undeleted_element( se );
|
||||
|
||||
return( *se );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_slist_element *lfds611_slist_get_next( struct lfds611_slist_element *se, struct lfds611_slist_element **next_se )
|
||||
{
|
||||
assert( se != NULL );
|
||||
assert( next_se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
*next_se = (struct lfds611_slist_element *) se->next;
|
||||
|
||||
lfds611_slist_internal_move_to_first_undeleted_element( next_se );
|
||||
|
||||
return( *next_se );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_slist_element *lfds611_slist_get_head_and_then_next( struct lfds611_slist_state *ss, struct lfds611_slist_element **se )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
if( *se == NULL )
|
||||
lfds611_slist_get_head( ss, se );
|
||||
else
|
||||
lfds611_slist_get_next( *se, se );
|
||||
|
||||
return( *se );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_internal_move_to_first_undeleted_element( struct lfds611_slist_element **se )
|
||||
{
|
||||
assert( se != NULL );
|
||||
|
||||
while( *se != NULL and (lfds611_atom_t) (*se)->user_data_and_flags[LFDS611_SLIST_FLAGS] & LFDS611_SLIST_FLAG_DELETED )
|
||||
(*se) = (struct lfds611_slist_element *) (*se)->next;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** defines *****/
|
||||
#define LFDS611_SLIST_USER_DATA 0
|
||||
#define LFDS611_SLIST_FLAGS 1
|
||||
|
||||
#define LFDS611_SLIST_NO_FLAGS 0x0
|
||||
#define LFDS611_SLIST_FLAG_DELETED 0x1
|
||||
|
||||
/***** structures *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_SINGLE_POINTER )
|
||||
|
||||
struct lfds611_slist_state {
|
||||
struct lfds611_slist_element
|
||||
*volatile head;
|
||||
|
||||
void
|
||||
(*user_data_delete_function)( void *user_data, void *user_state ),
|
||||
*user_state;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
/* TRD : this pragma pack doesn't seem to work under Windows
|
||||
if the structure members are the correct way round
|
||||
(next first), then user_data_and_flags ends up on
|
||||
a single pointer boundary and DCAS crashes
|
||||
|
||||
accordingly, I've moved user_data_and_flags first
|
||||
*/
|
||||
|
||||
struct lfds611_slist_element {
|
||||
void
|
||||
*volatile user_data_and_flags[2];
|
||||
|
||||
// TRD : requires volatile as is target of CAS
|
||||
struct lfds611_slist_element
|
||||
*volatile next;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
/***** private prototypes *****/
|
||||
void lfds611_slist_internal_init_slist( struct lfds611_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
|
||||
|
||||
void lfds611_slist_internal_link_element_to_head( struct lfds611_slist_state *lfds611_slist_state, struct lfds611_slist_element *volatile se );
|
||||
void lfds611_slist_internal_link_element_after_element( struct lfds611_slist_element *volatile lfds611_slist_in_list_element, struct lfds611_slist_element *volatile se );
|
||||
|
||||
void lfds611_slist_internal_move_to_first_undeleted_element( struct lfds611_slist_element **se );
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#include "lfds611_slist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_internal_link_element_to_head( struct lfds611_slist_state *ss, struct lfds611_slist_element *volatile se )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) struct lfds611_slist_element
|
||||
*se_next;
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
se_next = ss->head;
|
||||
|
||||
do {
|
||||
se->next = se_next;
|
||||
} while( se->next != (se_next = (struct lfds611_slist_element *) lfds611_abstraction_cas((volatile lfds611_atom_t *) &ss->head, (lfds611_atom_t) se, (lfds611_atom_t) se->next)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_internal_link_element_after_element( struct lfds611_slist_element *volatile lfds611_slist_in_list_element, struct lfds611_slist_element *volatile se )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) struct lfds611_slist_element
|
||||
*se_prev,
|
||||
*se_next;
|
||||
|
||||
assert( lfds611_slist_in_list_element != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
se_prev = (struct lfds611_slist_element *) lfds611_slist_in_list_element;
|
||||
|
||||
se_next = se_prev->next;
|
||||
|
||||
do {
|
||||
se->next = se_next;
|
||||
} while( se->next != (se_next = (struct lfds611_slist_element *) lfds611_abstraction_cas((volatile lfds611_atom_t *) &se_prev->next, (lfds611_atom_t) se, (lfds611_atom_t) se->next)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
#include "lfds611_slist_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_slist_new( struct lfds611_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
*ss = (struct lfds611_slist_state *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_slist_state), LFDS611_ALIGN_SINGLE_POINTER );
|
||||
|
||||
if( *ss != NULL ) {
|
||||
lfds611_slist_internal_init_slist( *ss, user_data_delete_function, user_state );
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_slist_use( struct lfds611_slist_state *ss )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_slist_internal_init_slist( struct lfds611_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
ss->head = NULL;
|
||||
ss->user_data_delete_function = user_data_delete_function;
|
||||
ss->user_state = user_state;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_slist_element *lfds611_slist_new_head( struct lfds611_slist_state *ss, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) struct lfds611_slist_element
|
||||
*volatile se;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
se = (struct lfds611_slist_element *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_slist_element), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( se != NULL ) {
|
||||
se->user_data_and_flags[LFDS611_SLIST_USER_DATA] = user_data;
|
||||
se->user_data_and_flags[LFDS611_SLIST_FLAGS] = LFDS611_SLIST_NO_FLAGS;
|
||||
|
||||
lfds611_slist_internal_link_element_to_head( ss, se );
|
||||
}
|
||||
|
||||
return( (struct lfds611_slist_element *) se );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
struct lfds611_slist_element *lfds611_slist_new_next( struct lfds611_slist_element *se, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) struct lfds611_slist_element
|
||||
*volatile se_next;
|
||||
|
||||
assert( se != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
se_next = (struct lfds611_slist_element *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_slist_element), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( se_next != NULL ) {
|
||||
se_next->user_data_and_flags[LFDS611_SLIST_USER_DATA] = user_data;
|
||||
se_next->user_data_and_flags[LFDS611_SLIST_FLAGS] = LFDS611_SLIST_NO_FLAGS;
|
||||
|
||||
lfds611_slist_internal_link_element_after_element( se, se_next );
|
||||
}
|
||||
|
||||
return( (struct lfds611_slist_element *) se_next );
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#include "lfds611_stack_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_delete( struct lfds611_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
void
|
||||
*user_data;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data_delete_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
while( lfds611_stack_pop(ss, &user_data) )
|
||||
if( user_data_delete_function != NULL )
|
||||
user_data_delete_function( user_data, user_state );
|
||||
|
||||
lfds611_freelist_delete( ss->fs, lfds611_stack_internal_freelist_delete_function, NULL );
|
||||
|
||||
lfds611_liblfds_aligned_free( ss );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_clear( struct lfds611_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state )
|
||||
{
|
||||
void
|
||||
*user_data;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data_clear_function can be NULL
|
||||
// TRD : user_state can be NULL
|
||||
|
||||
while( lfds611_stack_pop(ss, &user_data) )
|
||||
if( user_data_clear_function != NULL )
|
||||
user_data_clear_function( user_data, user_state );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_stack_internal_freelist_delete_function( void *user_data, void *user_state )
|
||||
{
|
||||
assert( user_data != NULL );
|
||||
assert( user_state == NULL );
|
||||
|
||||
lfds611_liblfds_aligned_free( user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/***** the library wide include file *****/
|
||||
#include "liblfds611_internal.h"
|
||||
|
||||
/***** pragmas *****/
|
||||
|
||||
/***** defines *****/
|
||||
#define LFDS611_STACK_POINTER 0
|
||||
#define LFDS611_STACK_COUNTER 1
|
||||
#define LFDS611_STACK_PAC_SIZE 2
|
||||
|
||||
/***** structures *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
struct lfds611_stack_state {
|
||||
// TRD : must come first for alignment
|
||||
struct lfds611_stack_element
|
||||
*volatile top[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
lfds611_atom_t
|
||||
aba_counter;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
};
|
||||
|
||||
struct lfds611_stack_element {
|
||||
struct lfds611_stack_element
|
||||
*next[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
/***** private prototypes *****/
|
||||
int lfds611_stack_internal_freelist_init_function( void **user_data, void *user_state );
|
||||
void lfds611_stack_internal_freelist_delete_function( void *user_data, void *user_state );
|
||||
|
||||
void lfds611_stack_internal_new_element_from_freelist( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], void *user_data );
|
||||
void lfds611_stack_internal_new_element( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], void *user_data );
|
||||
void lfds611_stack_internal_init_element( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], struct lfds611_freelist_element *fe, void *user_data );
|
||||
|
||||
void lfds611_stack_internal_push( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE] );
|
||||
|
||||
void lfds611_stack_internal_validate( struct lfds611_stack_state *ss, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *stack_validity,
|
||||
enum lfds611_data_structure_validity *freelist_validity );
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
#include "lfds611_stack_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_stack_new( struct lfds611_stack_state **ss, lfds611_atom_t number_elements )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : number_elements can be any value in its range
|
||||
|
||||
*ss = (struct lfds611_stack_state *) lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_stack_state), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *ss != NULL ) {
|
||||
// TRD : the size of the lfds611_freelist is the size of the lfds611_stack
|
||||
lfds611_freelist_new( &(*ss)->fs, number_elements, lfds611_stack_internal_freelist_init_function, NULL );
|
||||
|
||||
if( (*ss)->fs == NULL ) {
|
||||
lfds611_liblfds_aligned_free( *ss );
|
||||
*ss = NULL;
|
||||
}
|
||||
|
||||
if( (*ss)->fs != NULL ) {
|
||||
(*ss)->top[LFDS611_STACK_POINTER] = NULL;
|
||||
(*ss)->top[LFDS611_STACK_COUNTER] = 0;
|
||||
(*ss)->aba_counter = 0;
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
void lfds611_stack_use( struct lfds611_stack_state *ss )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
//#pragma warning( disable : 4100 )
|
||||
|
||||
int lfds611_stack_internal_freelist_init_function( void **user_data, void *user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
assert( user_data != NULL );
|
||||
assert( user_state == NULL );
|
||||
|
||||
*user_data = lfds611_liblfds_aligned_malloc( sizeof(struct lfds611_stack_element), LFDS611_ALIGN_DOUBLE_POINTER );
|
||||
|
||||
if( *user_data != NULL )
|
||||
rv = 1;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
//#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_internal_new_element_from_freelist( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], void *user_data )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
lfds611_freelist_pop( ss->fs, &fe );
|
||||
|
||||
if( fe == NULL )
|
||||
se[LFDS611_STACK_POINTER] = NULL;
|
||||
|
||||
if( fe != NULL )
|
||||
lfds611_stack_internal_init_element( ss, se, fe, user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_internal_new_element( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], void *user_data )
|
||||
{
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
lfds611_freelist_guaranteed_pop( ss->fs, &fe );
|
||||
|
||||
if( fe == NULL )
|
||||
se[LFDS611_STACK_POINTER] = NULL;
|
||||
|
||||
if( fe != NULL )
|
||||
lfds611_stack_internal_init_element( ss, se, fe, user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_internal_init_element( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE], struct lfds611_freelist_element *fe, void *user_data )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
assert( fe != NULL );
|
||||
// TRD : user_data can be any value in its range
|
||||
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &se[LFDS611_STACK_POINTER] );
|
||||
|
||||
se[LFDS611_STACK_COUNTER] = (struct lfds611_stack_element *) lfds611_abstraction_increment( (lfds611_atom_t *) &ss->aba_counter );
|
||||
|
||||
se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_POINTER] = NULL;
|
||||
se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_COUNTER] = 0;
|
||||
se[LFDS611_STACK_POINTER]->fe = fe;
|
||||
se[LFDS611_STACK_POINTER]->user_data = user_data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
#include "lfds611_stack_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_stack_push( struct lfds611_stack_state *ss, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element
|
||||
*se[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
lfds611_stack_internal_new_element_from_freelist( ss, se, user_data );
|
||||
|
||||
if( se[LFDS611_STACK_POINTER] == NULL )
|
||||
return( 0 );
|
||||
|
||||
lfds611_stack_internal_push( ss, se );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_stack_guaranteed_push( struct lfds611_stack_state *ss, void *user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element
|
||||
*se[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : user_data can be NULL
|
||||
|
||||
/* TRD : this function allocated a new lfds611_freelist element and uses that
|
||||
to push onto the lfds611_stack, guaranteeing success (unless malloc()
|
||||
fails of course)
|
||||
*/
|
||||
|
||||
lfds611_stack_internal_new_element( ss, se, user_data );
|
||||
|
||||
// TRD : malloc failed
|
||||
if( se[LFDS611_STACK_POINTER] == NULL )
|
||||
return( 0 );
|
||||
|
||||
lfds611_stack_internal_push( ss, se );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_internal_push( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE] )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element
|
||||
*original_se_next[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( se != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
original_se_next[LFDS611_STACK_POINTER] = ss->top[LFDS611_STACK_POINTER];
|
||||
original_se_next[LFDS611_STACK_COUNTER] = ss->top[LFDS611_STACK_COUNTER];
|
||||
|
||||
do {
|
||||
se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_POINTER] = original_se_next[LFDS611_STACK_POINTER];
|
||||
se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_COUNTER] = original_se_next[LFDS611_STACK_COUNTER];
|
||||
} while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) ss->top, (lfds611_atom_t *) se, (lfds611_atom_t *) original_se_next) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int lfds611_stack_pop( struct lfds611_stack_state *ss, void **user_data )
|
||||
{
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element
|
||||
*se[LFDS611_STACK_PAC_SIZE];
|
||||
|
||||
assert( ss != NULL );
|
||||
assert( user_data != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
se[LFDS611_STACK_COUNTER] = ss->top[LFDS611_STACK_COUNTER];
|
||||
se[LFDS611_STACK_POINTER] = ss->top[LFDS611_STACK_POINTER];
|
||||
|
||||
do {
|
||||
if( se[LFDS611_STACK_POINTER] == NULL )
|
||||
return( 0 );
|
||||
} while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) ss->top, (lfds611_atom_t *) se[LFDS611_STACK_POINTER]->next, (lfds611_atom_t *) se) );
|
||||
|
||||
*user_data = se[LFDS611_STACK_POINTER]->user_data;
|
||||
|
||||
lfds611_freelist_push( ss->fs, se[LFDS611_STACK_POINTER]->fe );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
#include "lfds611_stack_internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_query( struct lfds611_stack_state *ss, enum lfds611_stack_query_type query_type, void *query_input, void *query_output )
|
||||
{
|
||||
assert( ss != NULL );
|
||||
// TRD : query_type can be any value in its range
|
||||
// TRD : query_iput can be NULL
|
||||
assert( query_output != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
switch( query_type ) {
|
||||
case LFDS611_STACK_QUERY_ELEMENT_COUNT:
|
||||
assert( query_input == NULL );
|
||||
|
||||
lfds611_freelist_query( ss->fs, LFDS611_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
|
||||
break;
|
||||
|
||||
case LFDS611_STACK_QUERY_VALIDATE:
|
||||
// TRD : query_input can be NULL
|
||||
|
||||
/* TRD : the validation info passed in is for the stack
|
||||
it indicates the minimum and maximum number of elements
|
||||
which should be present
|
||||
|
||||
we need to validate the freelist
|
||||
and validate the stack
|
||||
|
||||
we cannot know the min/max for the freelist, given only
|
||||
the min/max for the stack
|
||||
*/
|
||||
|
||||
lfds611_freelist_query( ss->fs, LFDS611_FREELIST_QUERY_VALIDATE, NULL, (enum lfds611_data_structure_validity *) query_output );
|
||||
|
||||
if( *(enum lfds611_data_structure_validity *) query_output == LFDS611_VALIDITY_VALID )
|
||||
lfds611_stack_internal_validate( ss, (struct lfds611_validation_info *) query_input, (enum lfds611_data_structure_validity *) query_output, ((enum lfds611_data_structure_validity *) query_output)+1 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void lfds611_stack_internal_validate( struct lfds611_stack_state *ss, struct lfds611_validation_info *vi, enum lfds611_data_structure_validity *stack_validity,
|
||||
enum lfds611_data_structure_validity *freelist_validity )
|
||||
{
|
||||
struct lfds611_stack_element
|
||||
*se,
|
||||
*se_slow,
|
||||
*se_fast;
|
||||
|
||||
lfds611_atom_t
|
||||
element_count = 0,
|
||||
total_elements;
|
||||
|
||||
struct lfds611_validation_info
|
||||
freelist_vi;
|
||||
|
||||
assert( ss != NULL );
|
||||
// TRD : vi can be NULL
|
||||
assert( stack_validity != NULL );
|
||||
|
||||
*stack_validity = LFDS611_VALIDITY_VALID;
|
||||
|
||||
se_slow = se_fast = (struct lfds611_stack_element *) ss->top[LFDS611_STACK_POINTER];
|
||||
|
||||
/* TRD : first, check for a loop
|
||||
we have two pointers
|
||||
both of which start at the top of the stack
|
||||
we enter a loop
|
||||
and on each iteration
|
||||
we advance one pointer by one element
|
||||
and the other by two
|
||||
|
||||
we exit the loop when both pointers are NULL
|
||||
(have reached the end of the stack)
|
||||
|
||||
or
|
||||
|
||||
if we fast pointer 'sees' the slow pointer
|
||||
which means we have a loop
|
||||
*/
|
||||
|
||||
if( se_slow != NULL )
|
||||
do {
|
||||
se_slow = se_slow->next[LFDS611_STACK_POINTER];
|
||||
|
||||
if( se_fast != NULL )
|
||||
se_fast = se_fast->next[LFDS611_STACK_POINTER];
|
||||
|
||||
if( se_fast != NULL )
|
||||
se_fast = se_fast->next[LFDS611_STACK_POINTER];
|
||||
} while( se_slow != NULL and se_fast != se_slow );
|
||||
|
||||
if( se_fast != NULL and se_slow != NULL and se_fast == se_slow )
|
||||
*stack_validity = LFDS611_VALIDITY_INVALID_LOOP;
|
||||
|
||||
/* TRD : now check for expected number of elements
|
||||
vi can be NULL, in which case we do not check
|
||||
we know we don't have a loop from our earlier check
|
||||
*/
|
||||
|
||||
if( *stack_validity == LFDS611_VALIDITY_VALID and vi != NULL ) {
|
||||
se = (struct lfds611_stack_element *) ss->top[LFDS611_STACK_POINTER];
|
||||
|
||||
while( se != NULL ) {
|
||||
element_count++;
|
||||
se = (struct lfds611_stack_element *) se->next[LFDS611_STACK_POINTER];
|
||||
}
|
||||
|
||||
if( element_count < vi->min_elements )
|
||||
*stack_validity = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( element_count > vi->max_elements )
|
||||
*stack_validity = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
}
|
||||
|
||||
/* TRD : now we validate the freelist
|
||||
|
||||
we may be able to check for the expected number of
|
||||
elements in the freelist
|
||||
|
||||
if the caller has given us an expected min and max
|
||||
number of elements in the stack, then the total number
|
||||
of elements in the freelist, minus that min and max,
|
||||
gives us the expected number of elements in the
|
||||
freelist
|
||||
*/
|
||||
|
||||
if( vi != NULL ) {
|
||||
lfds611_freelist_query( ss->fs, LFDS611_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
|
||||
|
||||
freelist_vi.min_elements = total_elements - vi->max_elements;
|
||||
freelist_vi.max_elements = total_elements - vi->min_elements;
|
||||
|
||||
lfds611_freelist_query( ss->fs, LFDS611_FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
|
||||
}
|
||||
|
||||
if( vi == NULL )
|
||||
lfds611_freelist_query( ss->fs, LFDS611_FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/***** public prototypes *****/
|
||||
#include "liblfds611.h"
|
||||
|
||||
/***** defines *****/
|
||||
#define and &&
|
||||
#define or ||
|
||||
|
||||
#define RAISED 1
|
||||
#define LOWERED 0
|
||||
|
||||
#define NO_FLAGS 0x0
|
||||
|
||||
/***** private prototypes *****/
|
||||
void *lfds611_liblfds_aligned_malloc( size_t size, size_t align_in_bytes );
|
||||
void lfds611_liblfds_aligned_free( void *memory );
|
||||
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_cas( volatile lfds611_atom_t *destination, lfds611_atom_t exchange, lfds611_atom_t compare );
|
||||
static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare );
|
||||
static LFDS611_INLINE lfds611_atom_t lfds611_abstraction_increment( volatile lfds611_atom_t *value );
|
||||
|
||||
/***** inlined code *****/
|
||||
#include "lfds611_abstraction/lfds611_abstraction_cas.c"
|
||||
#include "lfds611_abstraction/lfds611_abstraction_dcas.c"
|
||||
#include "lfds611_abstraction/lfds611_abstraction_increment.c"
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
building test
|
||||
=============
|
||||
|
||||
Windows (user-mode)
|
||||
===================
|
||||
1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition (or
|
||||
later versions) to load "liblfds.sln". The "Win32" platform is x86,
|
||||
the "x64" platform is x64. The test programme provides the "Release"
|
||||
and "Debug" targets. The other targets ("Release DLL", "Release Lib",
|
||||
"Debug DLL" and "Debug Lib") are carried over will-nilly from the liblds
|
||||
library.
|
||||
|
||||
All builds will work, but DLL builds will require the DLL from liblfds
|
||||
to be placed into a location where the test executable can find it (e.g.
|
||||
the same directory).
|
||||
|
||||
2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
|
||||
you'll need to have run setenv.bat or the appropriate vcvars*.bat first;
|
||||
you can build for x64/64-bit and x86/32-bit - just run the correct batch
|
||||
file).
|
||||
|
||||
If liblfds has been built as a DLL, the DLL from liblfds needs to be
|
||||
placed into a location where the test executable can find it (e.g. the
|
||||
same directory).
|
||||
|
||||
Targets are "rel", "dbg" and "clean". You need to clean between switching
|
||||
targets.
|
||||
|
||||
Windows (kernel)
|
||||
================
|
||||
No build supported, since this is a command line utility.
|
||||
|
||||
Linux
|
||||
=====
|
||||
Use GNUmake to run "makefile.linux". Targets are "rel", "dbg" and
|
||||
"clean". You need to clean between switching targets.
|
||||
|
||||
If liblfds has been built as a shared object, the shared object file from
|
||||
liblfds will need to be placed somewhere the text executable can find it.
|
||||
|
||||
A convenient solution is to place the shared object file in the same
|
||||
directory as the text executable and set the environment variable
|
||||
"LD_LIBRARY_PATH" to ".", e.g. in bash;
|
||||
|
||||
export LD_LIBRARY_PATH=.
|
||||
|
||||
Remember to unset after finishing testing, or your system will continue
|
||||
to scan the current directory for shared object files.
|
||||
|
||||
unset LD_LIBRARY_PATH
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
##### paths #####
|
||||
BINDIR = bin
|
||||
INCDIR = ../liblfds611/inc
|
||||
LIBDIR = ../liblfds611/bin
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
##### misc #####
|
||||
QUIETLY = 1>nul 2>nul
|
||||
|
||||
##### sources, objects and libraries #####
|
||||
BINNAME = test
|
||||
BINARY = $(BINDIR)/$(BINNAME)
|
||||
SRCDIRS = .
|
||||
SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c
|
||||
OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
|
||||
SYSLIBS = -lpthread -lc -lm
|
||||
USRLIBS = -llfds611
|
||||
|
||||
##### CPU variants #####
|
||||
UNAME = $(shell uname -m)
|
||||
GCCARCH = -march=$(UNAME)
|
||||
|
||||
ifeq ($(UNAME),x86_64)
|
||||
GCCARCH = -march=core2
|
||||
endif
|
||||
|
||||
ifeq ($(findstring arm,$(UNAME)),arm)
|
||||
GCCARCH = -march=armv6k -marm
|
||||
endif
|
||||
|
||||
##### tools #####
|
||||
MAKE = make
|
||||
MFLAGS =
|
||||
|
||||
DG = gcc
|
||||
DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)"
|
||||
|
||||
CC = gcc
|
||||
CFBASE = -Wall -Wno-unknown-pragmas -std=c99 $(GCCARCH) -pthread -c -I"$(SRCDIR)" -I"$(INCDIR)"
|
||||
CFREL = -O2 -Wno-strict-aliasing
|
||||
CFDBG = -O0 -g
|
||||
|
||||
LD = gcc
|
||||
LFBASE = -L"$(LIBDIR)"
|
||||
LFREL = -O2 -s
|
||||
LFDBG = -O0 -g
|
||||
|
||||
##### variants #####
|
||||
CFLAGS = $(CFBASE) $(CFDBG)
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
|
||||
ifeq ($(MAKECMDGOALS),rel)
|
||||
CFLAGS = $(CFBASE) $(CFREL)
|
||||
LFLAGS = $(LFBASE) $(LFREL)
|
||||
endif
|
||||
|
||||
##### search paths #####
|
||||
vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
|
||||
|
||||
##### implicit rules #####
|
||||
$(OBJDIR)/%.o : %.c
|
||||
$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
##### explicit rules #####
|
||||
$(BINARY) : $(OBJECTS)
|
||||
$(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS)
|
||||
chmod +x $(BINARY)
|
||||
|
||||
##### phony #####
|
||||
.PHONY : clean rel dbg
|
||||
|
||||
clean :
|
||||
@rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d
|
||||
|
||||
rel : $(BINARY)
|
||||
dbg : $(BINARY)
|
||||
|
||||
##### dependencies #####
|
||||
-include $(DEPENDS)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
##### paths #####
|
||||
BINDIR = bin
|
||||
INCDIR = ../liblfds611/inc
|
||||
LIBDIR = ../liblfds611/bin
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
##### misc #####
|
||||
QUIETLY = 1>nul 2>nul
|
||||
|
||||
##### sources, objects and libraries #####
|
||||
BINNAME = test
|
||||
BINARY = $(BINDIR)\$(BINNAME).exe
|
||||
SRCDIRS = .
|
||||
SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c
|
||||
OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
|
||||
SYSLIBS = kernel32.lib
|
||||
USRLIBS = liblfds611.lib
|
||||
|
||||
##### tools #####
|
||||
MAKE = make
|
||||
MFLAGS =
|
||||
|
||||
CC = cl
|
||||
CFBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCLUDE)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D UNICODE /D _UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS
|
||||
CFREL = /Ox /DNDEBUG /MT
|
||||
CFDBG = /Od /Gm /Zi /D_DEBUG /MTd
|
||||
|
||||
LD = link
|
||||
LFBASE = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx
|
||||
LFREL = /incremental:no
|
||||
LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
|
||||
|
||||
##### variants #####
|
||||
CFLAGS = $(CFBASE) $(CFDBG)
|
||||
LFLAGS = $(LFBASE) $(LFDBG)
|
||||
CLIB = libcmtd.lib
|
||||
|
||||
ifeq ($(MAKECMDGOALS),rel)
|
||||
CFLAGS = $(CFBASE) $(CFREL)
|
||||
LFLAGS = $(LFBASE) $(LFREL)
|
||||
CLIB = libcmt.lib
|
||||
endif
|
||||
|
||||
##### search paths #####
|
||||
vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
|
||||
|
||||
##### implicit rules #####
|
||||
$(OBJDIR)/%.obj : %.c
|
||||
$(CC) $(CFLAGS) "/Fo$@" $<
|
||||
|
||||
##### explicit rules #####
|
||||
$(BINARY) : $(OBJECTS)
|
||||
$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY)
|
||||
|
||||
##### phony #####
|
||||
.PHONY : clean rel dbg
|
||||
|
||||
clean :
|
||||
@erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY)
|
||||
|
||||
rel : $(BINARY)
|
||||
dbg : $(BINARY)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/***** defines *****/
|
||||
#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
/* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
!WIN_KERNEL_BUILD indicates Windows user-mode
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
typedef HANDLE thread_state_t;
|
||||
typedef DWORD thread_return_t;
|
||||
#define CALLING_CONVENTION WINAPI
|
||||
#endif
|
||||
|
||||
#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
/* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
#include <wdm.h>
|
||||
typedef HANDLE thread_state_t;
|
||||
typedef VOID thread_return_t;
|
||||
#define CALLING_CONVENTION
|
||||
#endif
|
||||
|
||||
#if (defined __unix__ && defined __GNUC__)
|
||||
/* TRD : any UNIX on any CPU with GCC
|
||||
|
||||
__unix__ indicates Solaris, Linux, HPUX, etc
|
||||
__GNUC__ indicates GCC
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
typedef pthread_t thread_state_t;
|
||||
typedef void * thread_return_t;
|
||||
#define CALLING_CONVENTION
|
||||
#endif
|
||||
|
||||
typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state );
|
||||
|
||||
/***** public prototypes *****/
|
||||
unsigned int abstraction_cpu_count( void );
|
||||
int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state );
|
||||
void abstraction_thread_wait( thread_state_t thread_state );
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
!WIN_KERNEL_BUILD indicates Windows user-mode
|
||||
*/
|
||||
|
||||
unsigned int abstraction_cpu_count()
|
||||
{
|
||||
SYSTEM_INFO
|
||||
si;
|
||||
|
||||
GetNativeSystemInfo( &si );
|
||||
|
||||
return( (unsigned int) si.dwNumberOfProcessors );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
unsigned int abstraction_cpu_count()
|
||||
{
|
||||
unsigned int
|
||||
active_processor_count;
|
||||
|
||||
active_processor_count = KeQueryActiveProcessorCount( NULL );
|
||||
|
||||
return( active_processor_count );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined __linux__ && defined __GNUC__)
|
||||
|
||||
/* TRD : Linux on any CPU with GCC
|
||||
|
||||
this function I believe is Linux specific and varies by UNIX flavour
|
||||
|
||||
__linux__ indicates Linux
|
||||
__GNUC__ indicates GCC
|
||||
*/
|
||||
|
||||
unsigned int abstraction_cpu_count()
|
||||
{
|
||||
long int
|
||||
cpu_count;
|
||||
|
||||
cpu_count = sysconf( _SC_NPROCESSORS_ONLN );
|
||||
|
||||
return( (unsigned int) cpu_count );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
!WIN_KERNEL_BUILD indicates Windows user-mode
|
||||
*/
|
||||
|
||||
int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
DWORD
|
||||
thread_id;
|
||||
|
||||
DWORD_PTR
|
||||
affinity_mask,
|
||||
result;
|
||||
|
||||
assert( thread_state != NULL );
|
||||
// TRD : cpu can be any value in its range
|
||||
assert( thread_function != NULL );
|
||||
// TRD : thread_user_state can be NULL
|
||||
|
||||
affinity_mask = (DWORD_PTR) (1 << cpu);
|
||||
|
||||
*thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id );
|
||||
|
||||
result = SetThreadAffinityMask( *thread_state, affinity_mask );
|
||||
|
||||
if( *thread_state != NULL and result != 0 )
|
||||
rv = 1;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
|
||||
{
|
||||
int
|
||||
rv = 0;
|
||||
|
||||
KAFFINITY
|
||||
affinity_mask
|
||||
|
||||
NTSTATUS
|
||||
nts_create,
|
||||
nts_affinity;
|
||||
|
||||
assert( thread_state != NULL );
|
||||
// TRD : cpu can be any value in its range
|
||||
assert( thread_function != NULL );
|
||||
// TRD : thread_user_state can be NULL
|
||||
|
||||
affinity_mask = 1 << cpu;
|
||||
|
||||
nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state );
|
||||
|
||||
nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) );
|
||||
|
||||
if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS )
|
||||
rv = 1;
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined __unix__)
|
||||
|
||||
/* TRD : any UNIX on any CPU with any compiler
|
||||
|
||||
I assumed pthreads is available on any UNIX.
|
||||
|
||||
__unix__ indicates Solaris, Linux, HPUX, etc
|
||||
*/
|
||||
|
||||
int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
|
||||
{
|
||||
int
|
||||
rv = 0,
|
||||
rv_create;
|
||||
|
||||
pthread_attr_t
|
||||
attr;
|
||||
|
||||
cpu_set_t
|
||||
cpuset;
|
||||
|
||||
assert( thread_state != NULL );
|
||||
// TRD : cpu can be any value in its range
|
||||
assert( thread_function != NULL );
|
||||
// TRD : thread_user_state can be NULL
|
||||
|
||||
pthread_attr_init( &attr );
|
||||
|
||||
CPU_ZERO( &cpuset );
|
||||
CPU_SET( cpu, &cpuset );
|
||||
pthread_attr_setaffinity_np( &attr, sizeof(cpuset), &cpuset );
|
||||
|
||||
rv_create = pthread_create( thread_state, &attr, thread_function, thread_user_state );
|
||||
|
||||
if( rv_create == 0 )
|
||||
rv = 1;
|
||||
|
||||
pthread_attr_destroy( &attr );
|
||||
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
!WIN_KERNEL_BUILD indicates Windows user-mode
|
||||
*/
|
||||
|
||||
void abstraction_thread_wait( thread_state_t thread_state )
|
||||
{
|
||||
WaitForSingleObject( thread_state, INFINITE );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
|
||||
|
||||
/* TRD : any Windows on any CPU with the Microsoft C compiler
|
||||
|
||||
_WIN32 indicates 64-bit or 32-bit Windows
|
||||
_MSC_VER indicates Microsoft C compiler
|
||||
WIN_KERNEL_BUILD indicates Windows kernel
|
||||
*/
|
||||
|
||||
void abstraction_thread_wait( thread_state_t thread_state )
|
||||
{
|
||||
KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#if (defined __unix__)
|
||||
|
||||
/* TRD : any UNIX on any CPU with any compiler
|
||||
|
||||
I assumed pthreads is available on any UNIX.
|
||||
|
||||
__unix__ indicates Solaris, Linux, HPUX, etc
|
||||
*/
|
||||
|
||||
void abstraction_thread_wait( thread_state_t thread_state )
|
||||
{
|
||||
pthread_join( thread_state, NULL );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void benchmark_lfds611_freelist( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
thread_count,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
struct lfds611_freelist_benchmark
|
||||
*fb;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
lfds611_atom_t
|
||||
total_operations_for_full_test_for_all_cpus,
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
|
||||
|
||||
double
|
||||
mean_operations_per_second_per_cpu,
|
||||
difference_per_second_per_cpu,
|
||||
total_difference_per_second_per_cpu,
|
||||
std_dev_per_second_per_cpu,
|
||||
scalability;
|
||||
|
||||
/* TRD : here we benchmark the freelist
|
||||
|
||||
the benchmark is to have a single freelist
|
||||
where a worker thread busy-works popping and then pushing
|
||||
*/
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
fb = (struct lfds611_freelist_benchmark *) malloc( sizeof(struct lfds611_freelist_benchmark) * cpu_count );
|
||||
|
||||
// TRD : print the benchmark ID and CSV header
|
||||
printf( "\n"
|
||||
"Release %s Freelist Benchmark #1\n"
|
||||
"CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS611_RELEASE_NUMBER_STRING );
|
||||
|
||||
// TRD : we run CPU count times for scalability
|
||||
for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) {
|
||||
// TRD : initialisation
|
||||
lfds611_freelist_new( &fs, 1000, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(fb+loop)->fs = fs;
|
||||
(fb+loop)->operation_count = 0;
|
||||
}
|
||||
|
||||
// TRD : main test
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds611_freelist_thread_pop_and_push, fb+loop );
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
// TRD : post test math
|
||||
total_operations_for_full_test_for_all_cpus = 0;
|
||||
total_difference_per_second_per_cpu = 0;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count;
|
||||
|
||||
mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
|
||||
|
||||
if( thread_count == 1 )
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ ) {
|
||||
difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
|
||||
total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
|
||||
}
|
||||
|
||||
std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
|
||||
|
||||
scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
|
||||
|
||||
printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
|
||||
|
||||
// TRD : cleanup
|
||||
lfds611_freelist_delete( fs, NULL, NULL );
|
||||
}
|
||||
|
||||
free( fb );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_freelist_thread_pop_and_push( void *freelist_benchmark )
|
||||
{
|
||||
struct lfds611_freelist_benchmark
|
||||
*fb;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( freelist_benchmark != NULL );
|
||||
|
||||
fb = (struct lfds611_freelist_benchmark *) freelist_benchmark;
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_freelist_pop( fb->fs, &fe );
|
||||
lfds611_freelist_push( fb->fs, fe );
|
||||
|
||||
fb->operation_count += 2;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void benchmark_lfds611_queue( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
thread_count,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct lfds611_queue_benchmark
|
||||
*qb;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
lfds611_atom_t
|
||||
total_operations_for_full_test_for_all_cpus,
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
|
||||
|
||||
double
|
||||
mean_operations_per_second_per_cpu,
|
||||
difference_per_second_per_cpu,
|
||||
total_difference_per_second_per_cpu,
|
||||
std_dev_per_second_per_cpu,
|
||||
scalability;
|
||||
|
||||
/* TRD : here we benchmark the queue
|
||||
|
||||
the benchmark is to have a single queue
|
||||
where a worker thread busy-works dequeuing and then queuing
|
||||
*/
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
qb = (struct lfds611_queue_benchmark *) malloc( sizeof(struct lfds611_queue_benchmark) * cpu_count );
|
||||
|
||||
// TRD : print the benchmark ID and CSV header
|
||||
printf( "\n"
|
||||
"Release %s Queue Benchmark #1\n"
|
||||
"CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS611_RELEASE_NUMBER_STRING );
|
||||
|
||||
// TRD : we run CPU count times for scalability
|
||||
for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) {
|
||||
// TRD : initialisation
|
||||
lfds611_queue_new( &qs, 1000 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(qb+loop)->qs = qs;
|
||||
(qb+loop)->operation_count = 0;
|
||||
}
|
||||
|
||||
// TRD : populate the queue (we don't actually use the user data)
|
||||
for( loop = 0 ; loop < 500 ; loop++ )
|
||||
lfds611_queue_enqueue( qs, (void *) (lfds611_atom_t) loop );
|
||||
|
||||
// TRD : main test
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds611_queue_thread_delfds611_queue_and_enqueue, qb+loop );
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
// TRD : post test math
|
||||
total_operations_for_full_test_for_all_cpus = 0;
|
||||
total_difference_per_second_per_cpu = 0;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count;
|
||||
|
||||
mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
|
||||
|
||||
if( thread_count == 1 )
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ ) {
|
||||
difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
|
||||
total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
|
||||
}
|
||||
|
||||
std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
|
||||
|
||||
scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
|
||||
|
||||
printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
|
||||
|
||||
// TRD : cleanup
|
||||
lfds611_queue_delete( qs, NULL, NULL );
|
||||
}
|
||||
|
||||
free( qb );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_queue_thread_delfds611_queue_and_enqueue( void *queue_benchmark )
|
||||
{
|
||||
struct lfds611_queue_benchmark
|
||||
*qb;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( queue_benchmark != NULL );
|
||||
|
||||
qb = (struct lfds611_queue_benchmark *) queue_benchmark;
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_queue_dequeue( qb->qs, &user_data );
|
||||
lfds611_queue_enqueue( qb->qs, user_data );
|
||||
|
||||
qb->operation_count += 2;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void benchmark_lfds611_ringbuffer( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
thread_count,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
struct lfds611_ringbuffer_benchmark
|
||||
*rb;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
lfds611_atom_t
|
||||
total_operations_for_full_test_for_all_cpus,
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
|
||||
|
||||
double
|
||||
mean_operations_per_second_per_cpu,
|
||||
difference_per_second_per_cpu,
|
||||
total_difference_per_second_per_cpu,
|
||||
std_dev_per_second_per_cpu,
|
||||
scalability;
|
||||
|
||||
/* TRD : here we benchmark the ringbuffer
|
||||
|
||||
the benchmark is to have a single ringbuffer
|
||||
where a worker thread busy-works writing and then reading
|
||||
*/
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
rb = (struct lfds611_ringbuffer_benchmark *) malloc( sizeof(struct lfds611_ringbuffer_benchmark) * cpu_count );
|
||||
|
||||
// TRD : print the benchmark ID and CSV header
|
||||
printf( "\n"
|
||||
"Release %s Ringbuffer Benchmark #1\n"
|
||||
"CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS611_RELEASE_NUMBER_STRING );
|
||||
|
||||
// TRD : we run CPU count times for scalability
|
||||
for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) {
|
||||
// TRD : initialisation
|
||||
lfds611_ringbuffer_new( &rs, 1000, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(rb+loop)->rs = rs;
|
||||
(rb+loop)->operation_count = 0;
|
||||
}
|
||||
|
||||
// TRD : main test
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds611_ringbuffer_thread_write_and_read, rb+loop );
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
// TRD : post test math
|
||||
total_operations_for_full_test_for_all_cpus = 0;
|
||||
total_difference_per_second_per_cpu = 0;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count;
|
||||
|
||||
mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
|
||||
|
||||
if( thread_count == 1 )
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ ) {
|
||||
difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
|
||||
total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
|
||||
}
|
||||
|
||||
std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
|
||||
|
||||
scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
|
||||
|
||||
printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
|
||||
|
||||
// TRD : cleanup
|
||||
lfds611_ringbuffer_delete( rs, NULL, NULL );
|
||||
}
|
||||
|
||||
free( rb );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark )
|
||||
{
|
||||
struct lfds611_ringbuffer_benchmark
|
||||
*rb;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( ringbuffer_benchmark != NULL );
|
||||
|
||||
rb = (struct lfds611_ringbuffer_benchmark *) ringbuffer_benchmark;
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_ringbuffer_get_write_element( rb->rs, &fe, NULL );
|
||||
lfds611_ringbuffer_put_write_element( rb->rs, fe );
|
||||
|
||||
lfds611_ringbuffer_get_read_element( rb->rs, &fe );
|
||||
lfds611_ringbuffer_put_read_element( rb->rs, fe );
|
||||
|
||||
rb->operation_count += 2;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void benchmark_lfds611_stack( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
thread_count,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
struct lfds611_stack_benchmark
|
||||
*sb;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
lfds611_atom_t
|
||||
total_operations_for_full_test_for_all_cpus,
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
|
||||
|
||||
double
|
||||
mean_operations_per_second_per_cpu,
|
||||
difference_per_second_per_cpu,
|
||||
total_difference_per_second_per_cpu,
|
||||
std_dev_per_second_per_cpu,
|
||||
scalability;
|
||||
|
||||
/* TRD : here we benchmark the stack
|
||||
|
||||
the benchmark is to have a single stack
|
||||
where a worker thread busy-works pushing then popping
|
||||
*/
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
sb = (struct lfds611_stack_benchmark *) malloc( sizeof(struct lfds611_stack_benchmark) * cpu_count );
|
||||
|
||||
// TRD : print the benchmark ID and CSV header
|
||||
printf( "\n"
|
||||
"Release %s Stack Benchmark #1\n"
|
||||
"CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS611_RELEASE_NUMBER_STRING );
|
||||
|
||||
// TRD : we run CPU count times for scalability
|
||||
for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) {
|
||||
// TRD : initialisation
|
||||
lfds611_stack_new( &ss, 1000 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(sb+loop)->ss = ss;
|
||||
(sb+loop)->operation_count = 0;
|
||||
}
|
||||
|
||||
// TRD : main test
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds611_stack_thread_push_and_pop, sb+loop );
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
// TRD : post test math
|
||||
total_operations_for_full_test_for_all_cpus = 0;
|
||||
total_difference_per_second_per_cpu = 0;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ )
|
||||
total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count;
|
||||
|
||||
mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
|
||||
|
||||
if( thread_count == 1 )
|
||||
total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
|
||||
|
||||
for( loop = 0 ; loop < thread_count ; loop++ ) {
|
||||
difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
|
||||
total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
|
||||
}
|
||||
|
||||
std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
|
||||
|
||||
scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
|
||||
|
||||
printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
|
||||
|
||||
// TRD : cleanup
|
||||
lfds611_stack_delete( ss, NULL, NULL );
|
||||
}
|
||||
|
||||
free( sb );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_stack_thread_push_and_pop( void *stack_benchmark )
|
||||
{
|
||||
struct lfds611_stack_benchmark
|
||||
*sb;
|
||||
|
||||
void
|
||||
*user_data = NULL;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( stack_benchmark != NULL );
|
||||
|
||||
sb = (struct lfds611_stack_benchmark *) stack_benchmark;
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_stack_push( sb->ss, user_data );
|
||||
lfds611_stack_pop( sb->ss, &user_data );
|
||||
|
||||
sb->operation_count += 2;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/***** ANSI includes *****/
|
||||
/* TRD : _GNU_SOURCE is required by sched.h for pthread_attr_setaffinity_np, CPU_ZERO and CPU_SET
|
||||
however it has to be defined very early as even the ANSI headers pull in stuff
|
||||
which uses _GNU_SOURCE and which I think must be protected against multiple inclusion,
|
||||
which basically means if you set it too late, it's not seen, because the headers
|
||||
have already been parsed with _GNU_SOURCE unset
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
/***** internal includes *****/
|
||||
#include "abstraction.h"
|
||||
|
||||
/***** external includes *****/
|
||||
#include "liblfds611.h"
|
||||
|
||||
/***** defines *****/
|
||||
#define and &&
|
||||
#define or ||
|
||||
|
||||
#define RAISED 1
|
||||
#define LOWERED 0
|
||||
|
||||
#define NO_FLAGS 0x0
|
||||
|
||||
/***** enums *****/
|
||||
enum lfds611_test_operation {
|
||||
UNKNOWN,
|
||||
HELP,
|
||||
TEST,
|
||||
BENCHMARK
|
||||
};
|
||||
|
||||
/***** structs *****/
|
||||
#include "structures.h"
|
||||
|
||||
/***** prototypes *****/
|
||||
int main( int argc, char **argv );
|
||||
|
||||
void internal_display_test_name( char *test_name );
|
||||
void internal_display_test_result( unsigned int number_name_dvs_pairs, ... );
|
||||
void internal_display_lfds611_data_structure_validity( enum lfds611_data_structure_validity dvs );
|
||||
|
||||
void benchmark_lfds611_freelist( void );
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_freelist_thread_pop_and_push( void *freelist_benchmark );
|
||||
|
||||
void benchmark_lfds611_queue( void );
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_queue_thread_delfds611_queue_and_enqueue( void *queue_benchmark );
|
||||
|
||||
void benchmark_lfds611_ringbuffer( void );
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark );
|
||||
|
||||
void benchmark_lfds611_stack( void );
|
||||
thread_return_t CALLING_CONVENTION benchmark_lfds611_stack_thread_push_and_pop( void *stack_benchmark );
|
||||
|
||||
void test_lfds611_abstraction( void );
|
||||
void abstraction_test_increment( void );
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter );
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter );
|
||||
void abstraction_test_cas( void );
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state );
|
||||
void abstraction_test_dcas( void );
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state );
|
||||
|
||||
void test_lfds611_freelist( void );
|
||||
void freelist_test_internal_popping( void );
|
||||
int freelist_test_internal_popping_init( void **user_data, void *user_state );
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state );
|
||||
void freelist_test_internal_pushing( void );
|
||||
int freelist_test_internal_pushing_init( void **user_data, void *user_state );
|
||||
void freelist_test_internal_pushing_delete( void *user_data, void *user_state );
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state );
|
||||
void freelist_test_internal_popping_and_pushing( void );
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state );
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state );
|
||||
void freelist_test_internal_rapid_popping_and_pushing( void );
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds611_freelist_state );
|
||||
|
||||
void test_lfds611_queue( void );
|
||||
void queue_test_enqueuing( void );
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state );
|
||||
void queue_test_dequeuing( void );
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state );
|
||||
void queue_test_enqueuing_and_dequeuing( void );
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
|
||||
void queue_test_rapid_enqueuing_and_dequeuing( void );
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
|
||||
|
||||
void test_lfds611_ringbuffer( void );
|
||||
void ringbuffer_test_reading( void );
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state );
|
||||
void ringbuffer_test_writing( void );
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state );
|
||||
void ringbuffer_test_reading_and_writing( void );
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state );
|
||||
|
||||
void test_lfds611_slist( void );
|
||||
void test_slist_new_delete_get( void );
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_new_head_and_next( void *slist_test_state );
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_delete_and_get( void *slist_test_state );
|
||||
void test_slist_get_set_user_data( void );
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_get_set_user_data( void *slist_test_state );
|
||||
void test_slist_delete_all_elements( void );
|
||||
|
||||
void test_lfds611_stack( void );
|
||||
void stack_test_internal_popping( void );
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping( void *stack_test_popping_state );
|
||||
void stack_test_internal_pushing( void );
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_pushing( void *stack_test_pushing_state );
|
||||
void stack_test_internal_popping_and_pushing( void );
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_popping( void *stack_test_popping_and_pushing_state );
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_pushing( void *stack_test_popping_and_pushing_state );
|
||||
void stack_test_internal_rapid_popping_and_pushing( void );
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_rapid_popping_and_pushing( void *stack_state );
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
enum lfds611_test_operation
|
||||
operation = UNKNOWN;
|
||||
|
||||
unsigned int
|
||||
loop,
|
||||
iterations = 1;
|
||||
|
||||
assert( argc >= 1 );
|
||||
assert( argv != NULL );
|
||||
|
||||
if( argc == 1 or argc >= 4 )
|
||||
operation = HELP;
|
||||
|
||||
if( operation == UNKNOWN ) {
|
||||
if( 0 == strcmp(*(argv+1), "test") ) {
|
||||
operation = TEST;
|
||||
|
||||
// TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay
|
||||
if( argc == 3 )
|
||||
sscanf( *(argv+2), "%u", &iterations );
|
||||
}
|
||||
|
||||
if( 0 == strcmp(*(argv+1), "benchmark") ) {
|
||||
operation = BENCHMARK;
|
||||
|
||||
// TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay
|
||||
if( argc == 3 )
|
||||
sscanf( *(argv+2), "%u", &iterations );
|
||||
}
|
||||
}
|
||||
|
||||
switch( operation ) {
|
||||
case UNKNOWN:
|
||||
case HELP:
|
||||
printf( "test [test|benchmark] [iterations]\n"
|
||||
" test : run the test suite\n"
|
||||
" benchmark : run the benchmark suite\n"
|
||||
" iterations : optional, default is 1\n" );
|
||||
break;
|
||||
|
||||
case TEST:
|
||||
for( loop = 1 ; loop < iterations+1 ; loop++ ) {
|
||||
printf( "\n"
|
||||
"Test Iteration %02u\n"
|
||||
"=================\n", loop );
|
||||
|
||||
test_lfds611_abstraction();
|
||||
test_lfds611_freelist();
|
||||
test_lfds611_queue();
|
||||
test_lfds611_ringbuffer();
|
||||
test_lfds611_slist();
|
||||
test_lfds611_stack();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BENCHMARK:
|
||||
for( loop = 1 ; loop < iterations+1 ; loop++ ) {
|
||||
printf( "\n"
|
||||
"Benchmark Iteration %02u\n"
|
||||
"========================\n", loop );
|
||||
|
||||
benchmark_lfds611_freelist();
|
||||
benchmark_lfds611_queue();
|
||||
benchmark_lfds611_ringbuffer();
|
||||
benchmark_lfds611_stack();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void internal_display_test_name( char *test_name )
|
||||
{
|
||||
assert( test_name != NULL );
|
||||
|
||||
printf( "%s...", test_name );
|
||||
fflush( stdout );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void internal_display_test_result( unsigned int number_name_dvs_pairs, ... )
|
||||
{
|
||||
va_list
|
||||
va;
|
||||
|
||||
int
|
||||
passed_flag = RAISED;
|
||||
|
||||
unsigned int
|
||||
loop;
|
||||
|
||||
char
|
||||
*name;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs;
|
||||
|
||||
// TRD : number_name_dvs_pairs can be any value in its range
|
||||
|
||||
va_start( va, number_name_dvs_pairs );
|
||||
|
||||
for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) {
|
||||
name = va_arg( va, char * );
|
||||
dvs = va_arg( va, enum lfds611_data_structure_validity );
|
||||
|
||||
if( dvs != LFDS611_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 lfds611_data_structure_validity );
|
||||
|
||||
printf( "%s ", name );
|
||||
internal_display_lfds611_data_structure_validity( dvs );
|
||||
|
||||
if( loop+1 < number_name_dvs_pairs )
|
||||
printf( ", " );
|
||||
}
|
||||
|
||||
va_end( va );
|
||||
|
||||
printf( ")\n" );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void internal_display_lfds611_data_structure_validity( enum lfds611_data_structure_validity dvs )
|
||||
{
|
||||
char
|
||||
*string = NULL;
|
||||
|
||||
switch( dvs ) {
|
||||
case LFDS611_VALIDITY_VALID:
|
||||
string = "valid";
|
||||
break;
|
||||
|
||||
case LFDS611_VALIDITY_INVALID_LOOP:
|
||||
string = "invalid - loop detected";
|
||||
break;
|
||||
|
||||
case LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS:
|
||||
string = "invalid - missing elements";
|
||||
break;
|
||||
|
||||
case LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS:
|
||||
string = "invalid - additional elements";
|
||||
break;
|
||||
|
||||
case LFDS611_VALIDITY_INVALID_TEST_DATA:
|
||||
string = "invalid - invalid test data";
|
||||
break;
|
||||
}
|
||||
|
||||
printf( "%s", string );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
/***** structs *****/
|
||||
#pragma pack( push, LFDS611_ALIGN_DOUBLE_POINTER )
|
||||
|
||||
/***** abstraction tests *****/
|
||||
struct abstraction_test_cas_state {
|
||||
volatile lfds611_atom_t
|
||||
*shared_counter;
|
||||
|
||||
lfds611_atom_t
|
||||
local_counter;
|
||||
};
|
||||
|
||||
struct abstraction_test_dcas_state {
|
||||
volatile lfds611_atom_t
|
||||
*shared_counter;
|
||||
|
||||
lfds611_atom_t
|
||||
local_counter;
|
||||
};
|
||||
|
||||
/***** freelist tests *****/
|
||||
struct freelist_test_popping_state {
|
||||
struct lfds611_freelist_state
|
||||
*fs,
|
||||
*fs_thread_local;
|
||||
};
|
||||
|
||||
struct freelist_test_pushing_state {
|
||||
lfds611_atom_t
|
||||
*count,
|
||||
thread_number;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*source_fs,
|
||||
*fs;
|
||||
};
|
||||
|
||||
struct freelist_test_popping_and_pushing_state {
|
||||
struct lfds611_freelist_state
|
||||
*local_fs,
|
||||
*fs;
|
||||
};
|
||||
|
||||
struct freelist_test_counter_and_thread_number {
|
||||
lfds611_atom_t
|
||||
thread_number;
|
||||
|
||||
unsigned long long int
|
||||
counter;
|
||||
};
|
||||
|
||||
/***** queue tests *****/
|
||||
struct queue_test_enqueuing_state {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
lfds611_atom_t
|
||||
counter;
|
||||
};
|
||||
|
||||
struct queue_test_dequeuing_state {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
int
|
||||
error_flag;
|
||||
};
|
||||
|
||||
struct queue_test_enqueuing_and_dequeuing_state {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
lfds611_atom_t
|
||||
counter,
|
||||
thread_number,
|
||||
*per_thread_counters;
|
||||
|
||||
unsigned int
|
||||
cpu_count;
|
||||
|
||||
int
|
||||
error_flag;
|
||||
};
|
||||
|
||||
struct queue_test_rapid_enqueuing_and_dequeuing_state {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
lfds611_atom_t
|
||||
counter;
|
||||
};
|
||||
|
||||
/***** ringbuffer tests *****/
|
||||
struct ringbuffer_test_reading_state {
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
int
|
||||
error_flag;
|
||||
|
||||
lfds611_atom_t
|
||||
read_count;
|
||||
};
|
||||
|
||||
struct ringbuffer_test_writing_state {
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
lfds611_atom_t
|
||||
write_count;
|
||||
};
|
||||
|
||||
struct ringbuffer_test_reading_and_writing_state {
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
lfds611_atom_t
|
||||
counter,
|
||||
*per_thread_counters;
|
||||
|
||||
unsigned int
|
||||
cpu_count;
|
||||
|
||||
int
|
||||
error_flag;
|
||||
};
|
||||
|
||||
/***** slist tests *****/
|
||||
struct slist_test_state {
|
||||
struct lfds611_slist_state
|
||||
*ss;
|
||||
|
||||
size_t
|
||||
create_count,
|
||||
delete_count;
|
||||
|
||||
lfds611_atom_t
|
||||
thread_and_count;
|
||||
};
|
||||
|
||||
/***** stack tests *****/
|
||||
struct stack_test_popping_state {
|
||||
struct lfds611_stack_state
|
||||
*ss,
|
||||
*ss_thread_local;
|
||||
};
|
||||
|
||||
struct stack_test_pushing_state {
|
||||
lfds611_atom_t
|
||||
thread_number;
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
};
|
||||
|
||||
struct stack_test_popping_and_pushing_state {
|
||||
struct lfds611_stack_state
|
||||
*local_ss,
|
||||
*ss;
|
||||
};
|
||||
|
||||
struct stack_test_counter_and_thread_number {
|
||||
lfds611_atom_t
|
||||
thread_number,
|
||||
counter;
|
||||
};
|
||||
|
||||
/***** freelist benchmarks *****/
|
||||
struct lfds611_freelist_benchmark {
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
lfds611_atom_t
|
||||
operation_count;
|
||||
};
|
||||
|
||||
/***** queue benchmarks *****/
|
||||
struct lfds611_queue_benchmark {
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
lfds611_atom_t
|
||||
operation_count;
|
||||
};
|
||||
|
||||
/***** ringbuffer benchmarks *****/
|
||||
struct lfds611_ringbuffer_benchmark {
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
lfds611_atom_t
|
||||
operation_count;
|
||||
};
|
||||
|
||||
/***** stack benchmarks *****/
|
||||
struct lfds611_stack_benchmark {
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
lfds611_atom_t
|
||||
operation_count;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
@@ -1,323 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_abstraction( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"Abstraction Tests\n"
|
||||
"=================\n" );
|
||||
|
||||
abstraction_test_increment();
|
||||
abstraction_test_cas();
|
||||
abstraction_test_dcas();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void abstraction_test_increment( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
|
||||
shared_counter,
|
||||
atomic_shared_counter;
|
||||
|
||||
/* TRD : here we test lfds611_abstraction_increment
|
||||
|
||||
first, we run one thread per CPU where each thread increments
|
||||
a shared counter 10,000,000 times - however, this first test
|
||||
does NOT use atomic increment; it uses "++"
|
||||
|
||||
second, we repeat the exercise, but this time using
|
||||
lfds611_abstraction_increment()
|
||||
|
||||
if the final value in the first test is less than (10,000,000*cpu_count)
|
||||
then the system is sensitive to non-atomic increments; this means if
|
||||
our atomic version of the test passes, we can have some degree of confidence
|
||||
that it works
|
||||
|
||||
if the final value in the first test is in fact correct, then we can't know
|
||||
that our atomic version has changed anything
|
||||
|
||||
and of course if the final value in the atomic test is wrong, we know things
|
||||
are broken
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Atomic increment" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
shared_counter = 0;
|
||||
atomic_shared_counter = 0;
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
// TRD : non-atomic
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, (void *) &shared_counter );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
// TRD : atomic
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, (void *) &atomic_shared_counter );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : results
|
||||
if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
|
||||
puts( "passed" );
|
||||
|
||||
if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
|
||||
puts( "indeterminate" );
|
||||
|
||||
if( atomic_shared_counter < (10000000 * cpu_count) )
|
||||
puts( "failed" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
|
||||
{
|
||||
assert( shared_counter != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
lfds611_liblfds_abstraction_test_helper_increment_non_atomic( shared_counter );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
|
||||
{
|
||||
assert( shared_counter != NULL );
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
lfds611_liblfds_abstraction_test_helper_increment_atomic( shared_counter );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void abstraction_test_cas( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct abstraction_test_cas_state
|
||||
*atcs;
|
||||
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
|
||||
shared_counter;
|
||||
|
||||
lfds611_atom_t
|
||||
local_total = 0;
|
||||
|
||||
// TRD : number_logical_processors can be any value in its range
|
||||
|
||||
/* TRD : here we test lfds611_abstraction_cas
|
||||
|
||||
we run one thread per CPU
|
||||
we use lfds611_abstraction_cas() to increment a shared counter
|
||||
every time a thread successfully increments the counter,
|
||||
it increments a thread local counter
|
||||
the threads run for ten seconds
|
||||
after the threads finish, we total the local counters
|
||||
they should equal the shared counter
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Atomic CAS" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
shared_counter = 0;
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(atcs+loop)->shared_counter = &shared_counter;
|
||||
(atcs+loop)->local_counter = 0;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : results
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
local_total += (atcs+loop)->local_counter;
|
||||
|
||||
if( local_total == shared_counter )
|
||||
puts( "passed" );
|
||||
|
||||
if( local_total != shared_counter )
|
||||
puts( "failed" );
|
||||
|
||||
// TRD : cleanup
|
||||
free( atcs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state )
|
||||
{
|
||||
struct abstraction_test_cas_state
|
||||
*atcs;
|
||||
|
||||
assert( abstraction_test_cas_state != NULL );
|
||||
|
||||
atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state;
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
lfds611_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void abstraction_test_dcas( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct abstraction_test_dcas_state
|
||||
*atds;
|
||||
|
||||
LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) volatile lfds611_atom_t
|
||||
shared_counter[2] = { 0, 0 };
|
||||
|
||||
lfds611_atom_t
|
||||
local_total = 0;
|
||||
|
||||
/* TRD : here we test lfds611_abstraction_dcas
|
||||
|
||||
we run one thread per CPU
|
||||
we use lfds611_abstraction_dcas() to increment a shared counter
|
||||
every time a thread successfully increments the counter,
|
||||
it increments a thread local counter
|
||||
the threads run for ten seconds
|
||||
after the threads finish, we total the local counters
|
||||
they should equal the shared counter
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Atomic DCAS" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(atds+loop)->shared_counter = shared_counter;
|
||||
(atds+loop)->local_counter = 0;
|
||||
}
|
||||
|
||||
LFDS611_BARRIER_STORE;
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : results
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
local_total += (atds+loop)->local_counter;
|
||||
|
||||
if( local_total == shared_counter[0] )
|
||||
puts( "passed" );
|
||||
|
||||
if( local_total != shared_counter[0] )
|
||||
puts( "failed" );
|
||||
|
||||
// TRD : cleanup
|
||||
free( atds );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
|
||||
{
|
||||
struct abstraction_test_dcas_state
|
||||
*atds;
|
||||
|
||||
assert( abstraction_test_dcas_state != NULL );
|
||||
|
||||
atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
|
||||
|
||||
LFDS611_BARRIER_LOAD;
|
||||
|
||||
lfds611_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,673 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_freelist( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"Freelist Tests\n"
|
||||
"==============\n" );
|
||||
|
||||
freelist_test_internal_popping();
|
||||
freelist_test_internal_pushing();
|
||||
freelist_test_internal_popping_and_pushing();
|
||||
freelist_test_internal_rapid_popping_and_pushing();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void freelist_test_internal_popping( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
lfds611_atom_t
|
||||
count = 0;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs = LFDS611_VALIDITY_VALID;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
struct freelist_test_popping_state
|
||||
*ftps;
|
||||
|
||||
unsigned int
|
||||
*found_count;
|
||||
|
||||
/* TRD : we create a freelist with 1,000,000 elements
|
||||
|
||||
the creation function runs in a single thread and creates
|
||||
and pushes those elements onto the freelist
|
||||
|
||||
each element contains a void pointer which is its element number
|
||||
|
||||
we then run one thread per CPU
|
||||
where each thread loops, popping as quickly as possible
|
||||
each popped element is pushed onto a thread-local freelist
|
||||
|
||||
the threads run till the source freelist is empty
|
||||
|
||||
we then check the thread-local freelists
|
||||
we should find we have every element
|
||||
|
||||
then tidy up
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Popping" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_freelist_new( &fs, 1000000, freelist_test_internal_popping_init, &count );
|
||||
ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(ftps+loop)->fs = fs;
|
||||
lfds611_freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL );
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : now we check the thread-local freelists
|
||||
found_count = malloc( sizeof(unsigned int) * 1000000 );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ )
|
||||
*(found_count+loop) = 0;
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
while( lfds611_freelist_pop((ftps+loop)->fs_thread_local, &fe) ) {
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &count );
|
||||
(*(found_count+count))++;
|
||||
lfds611_freelist_push( fs, fe );
|
||||
}
|
||||
}
|
||||
|
||||
for( loop = 0 ; loop < 1000000 and dvs == LFDS611_VALIDITY_VALID ; loop++ ) {
|
||||
if( *(found_count+loop) == 0 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( *(found_count+loop) > 1 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
}
|
||||
|
||||
// TRD : cleanup
|
||||
free( found_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
lfds611_freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL );
|
||||
|
||||
free( ftps );
|
||||
lfds611_freelist_delete( fs, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 1, "freelist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#pragma warning( disable : 4100 )
|
||||
|
||||
int freelist_test_internal_popping_init( void **user_data, void *user_state )
|
||||
{
|
||||
lfds611_atom_t
|
||||
*count;
|
||||
|
||||
assert( user_data != NULL );
|
||||
assert( user_state != NULL );
|
||||
|
||||
count = (lfds611_atom_t *) user_state;
|
||||
|
||||
*(lfds611_atom_t *) user_data = (*count)++;
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state )
|
||||
{
|
||||
struct freelist_test_popping_state
|
||||
*ftps;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( freelist_test_popping_state != NULL );
|
||||
|
||||
ftps = (struct freelist_test_popping_state *) freelist_test_popping_state;
|
||||
|
||||
lfds611_freelist_use( ftps->fs );
|
||||
lfds611_freelist_use( ftps->fs_thread_local );
|
||||
|
||||
while( lfds611_freelist_pop(ftps->fs, &fe) )
|
||||
lfds611_freelist_push( ftps->fs_thread_local, fe );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void freelist_test_internal_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
lfds611_atom_t
|
||||
count = 0;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs;
|
||||
|
||||
struct freelist_test_pushing_state
|
||||
*ftps;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs,
|
||||
*cleanup_fs;
|
||||
|
||||
struct freelist_test_counter_and_thread_number
|
||||
*cnt,
|
||||
*counter_and_number_trackers;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi;
|
||||
|
||||
/* TRD : we create an empty freelist, which we will push to
|
||||
|
||||
we then create one freelist per CPU, where this freelist
|
||||
contains 100,000 elements per thread and
|
||||
each element is an incrementing counter and unique ID
|
||||
(from 0 to number of CPUs)
|
||||
|
||||
we then start one thread per CPU, where each thread is
|
||||
given one of the populated freelists and pops from that
|
||||
to push to the empty freelist
|
||||
|
||||
the reason for this is to achieve memory pre-allocation
|
||||
which allows the pushing threads to run at maximum speed
|
||||
|
||||
the threads end when their freelists are empty
|
||||
|
||||
we then fully pop the now populated main freelist (onto
|
||||
a second freelist, so we can cleanly free all memory),
|
||||
checking that the counts increment on a per unique ID basis
|
||||
and that the number of elements we pop equals 1,000,000 per thread
|
||||
(since each element has an incrementing counter which is
|
||||
unique on a per unique ID basis, we can know we didn't lose
|
||||
any elements)
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Pushing" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
ftps = malloc( sizeof(struct freelist_test_pushing_state) * cpu_count );
|
||||
|
||||
lfds611_freelist_new( &fs, 0, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(ftps+loop)->thread_number = (lfds611_atom_t) loop;
|
||||
// TRD : note count is shared across threads, so thread 0 is 0-100000, thread 1 is 100000-200000, etc
|
||||
(ftps+loop)->count = &count;
|
||||
lfds611_freelist_new( &(ftps+loop)->source_fs, 100000, freelist_test_internal_pushing_init, (void *) (ftps+loop) );
|
||||
(ftps+loop)->fs = fs;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_pushing, ftps+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : now fully pop and verify the main freelist
|
||||
lfds611_freelist_new( &cleanup_fs, 0, NULL, NULL );
|
||||
|
||||
counter_and_number_trackers = malloc( sizeof(struct freelist_test_counter_and_thread_number) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(counter_and_number_trackers+loop)->counter = 100000 * loop;
|
||||
(counter_and_number_trackers+loop)->thread_number = (lfds611_atom_t) loop;
|
||||
}
|
||||
|
||||
vi.min_elements = vi.max_elements = 100000 * cpu_count;
|
||||
|
||||
lfds611_freelist_query( fs, LFDS611_FREELIST_QUERY_VALIDATE, &vi, (void *) &dvs );
|
||||
|
||||
while( dvs == LFDS611_VALIDITY_VALID and lfds611_freelist_pop(fs, &fe) ) {
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &cnt );
|
||||
|
||||
if( cnt->counter != (counter_and_number_trackers+cnt->thread_number)->counter++ )
|
||||
dvs = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
lfds611_freelist_push( cleanup_fs, fe );
|
||||
}
|
||||
|
||||
// TRD : clean up
|
||||
free( counter_and_number_trackers );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
lfds611_freelist_delete( (ftps+loop)->source_fs, NULL, NULL );
|
||||
|
||||
free( ftps );
|
||||
|
||||
lfds611_freelist_delete( cleanup_fs, freelist_test_internal_pushing_delete, NULL );
|
||||
lfds611_freelist_delete( fs, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 1, "freelist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
int freelist_test_internal_pushing_init( void **user_data, void *user_state )
|
||||
{
|
||||
struct freelist_test_counter_and_thread_number
|
||||
*ftcatn;
|
||||
|
||||
struct freelist_test_pushing_state
|
||||
*ftps;
|
||||
|
||||
assert( user_data != NULL );
|
||||
// TRD : user_state is being used as an integer type
|
||||
|
||||
*user_data = malloc( sizeof(struct freelist_test_counter_and_thread_number) );
|
||||
ftps = (struct freelist_test_pushing_state *) user_state;
|
||||
|
||||
ftcatn = (struct freelist_test_counter_and_thread_number *) *user_data;
|
||||
|
||||
ftcatn->counter = (*ftps->count)++;
|
||||
ftcatn->thread_number = ftps->thread_number;
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
#pragma warning( disable : 4100 )
|
||||
|
||||
void freelist_test_internal_pushing_delete( void *user_data, void *user_state )
|
||||
{
|
||||
assert( user_data != NULL );
|
||||
assert( user_state == NULL );
|
||||
|
||||
free( user_data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma warning( default : 4100 )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state )
|
||||
{
|
||||
struct freelist_test_pushing_state
|
||||
*ftps;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
assert( freelist_test_pushing_state != NULL );
|
||||
|
||||
ftps = (struct freelist_test_pushing_state *) freelist_test_pushing_state;
|
||||
|
||||
lfds611_freelist_use( ftps->source_fs );
|
||||
lfds611_freelist_use( ftps->fs );
|
||||
|
||||
while( lfds611_freelist_pop(ftps->source_fs, &fe) )
|
||||
lfds611_freelist_push( ftps->fs, fe );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void freelist_test_internal_popping_and_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
struct freelist_test_popping_and_pushing_state
|
||||
*pps;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi;
|
||||
|
||||
/* TRD : we have two threads per CPU
|
||||
the threads loop for ten seconds
|
||||
the first thread pushes 100000 elements then pops 100000 elements
|
||||
the second thread pops 100000 elements then pushes 100000 elements
|
||||
all pushes and pops go onto the single main freelist
|
||||
|
||||
after time is up, all threads push what they have remaining onto
|
||||
the main freelist
|
||||
|
||||
we then validate the main freelist
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Popping and pushing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_freelist_new( &fs, 100000 * cpu_count, NULL, NULL );
|
||||
|
||||
pps = malloc( sizeof(struct freelist_test_popping_and_pushing_state) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(pps+loop)->fs = fs;
|
||||
lfds611_freelist_new( &(pps+loop)->local_fs, 0, NULL, NULL );
|
||||
|
||||
(pps+loop+cpu_count)->fs = fs;
|
||||
lfds611_freelist_new( &(pps+loop+cpu_count)->local_fs, 100000, NULL, NULL );
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping_and_pushing_start_popping, pps+loop );
|
||||
abstraction_thread_start( &thread_handles[loop+cpu_count], loop, freelist_test_internal_thread_popping_and_pushing_start_pushing, pps+loop+cpu_count );
|
||||
}
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
|
||||
lfds611_freelist_delete( (pps+loop)->local_fs, NULL, NULL );
|
||||
|
||||
free( pps );
|
||||
|
||||
vi.min_elements = vi.max_elements = 100000 * cpu_count * 2;
|
||||
|
||||
lfds611_freelist_query( fs, LFDS611_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs );
|
||||
|
||||
lfds611_freelist_delete( fs, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 1, "freelist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state )
|
||||
{
|
||||
struct freelist_test_popping_and_pushing_state
|
||||
*pps;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
unsigned int
|
||||
count;
|
||||
|
||||
assert( freelist_test_popping_and_pushing_state != NULL );
|
||||
|
||||
pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state;
|
||||
|
||||
lfds611_freelist_use( pps->fs );
|
||||
lfds611_freelist_use( pps->local_fs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
count = 0;
|
||||
|
||||
while( count < 100000 ) {
|
||||
lfds611_freelist_pop( pps->fs, &fe );
|
||||
|
||||
if( fe != NULL ) {
|
||||
lfds611_freelist_push( pps->local_fs, fe );
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
while( lfds611_freelist_pop(pps->local_fs, &fe) )
|
||||
lfds611_freelist_push( pps->fs, fe );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state )
|
||||
{
|
||||
struct freelist_test_popping_and_pushing_state
|
||||
*pps;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
unsigned int
|
||||
count;
|
||||
|
||||
assert( freelist_test_popping_and_pushing_state != NULL );
|
||||
|
||||
pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state;
|
||||
|
||||
lfds611_freelist_use( pps->fs );
|
||||
lfds611_freelist_use( pps->local_fs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
while( lfds611_freelist_pop(pps->local_fs, &fe) )
|
||||
lfds611_freelist_push( pps->fs, fe );
|
||||
|
||||
count = 0;
|
||||
|
||||
while( count < 1000 ) {
|
||||
lfds611_freelist_pop( pps->fs, &fe );
|
||||
|
||||
if( fe != NULL ) {
|
||||
lfds611_freelist_push( pps->local_fs, fe );
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TRD : now push whatever we have in our local freelist
|
||||
while( lfds611_freelist_pop(pps->local_fs, &fe) )
|
||||
lfds611_freelist_push( pps->fs, fe );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void freelist_test_internal_rapid_popping_and_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs;
|
||||
|
||||
/* TRD : in these tests there is a fundamental antagonism between
|
||||
how much checking/memory clean up that we do and the
|
||||
likelyhood of collisions between threads in their lock-free
|
||||
operations
|
||||
|
||||
the lock-free operations are very quick; if we do anything
|
||||
much at all between operations, we greatly reduce the chance
|
||||
of threads colliding
|
||||
|
||||
so we have some tests which do enough checking/clean up that
|
||||
they can tell the freelist is valid and don't leak memory
|
||||
and here, this test now is one of those which does minimal
|
||||
checking - in fact, the nature of the test is that you can't
|
||||
do any real checking - but goes very quickly
|
||||
|
||||
what we do is create a small freelist and then run one thread
|
||||
per CPU, where each thread simply pops and then immediately
|
||||
pushes
|
||||
|
||||
the test runs for ten seconds
|
||||
|
||||
after the test is done, the only check we do is to traverse
|
||||
the freelist, checking for loops and ensuring the number of
|
||||
elements is correct
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_freelist_new( &fs, cpu_count, NULL, NULL );
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_rapid_popping_and_pushing, fs );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
vi.min_elements = cpu_count;
|
||||
vi.max_elements = cpu_count;
|
||||
|
||||
lfds611_freelist_query( fs, LFDS611_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs );
|
||||
|
||||
lfds611_freelist_delete( fs, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 1, "freelist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds611_freelist_state )
|
||||
{
|
||||
struct lfds611_freelist_state
|
||||
*fs;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( lfds611_freelist_state != NULL );
|
||||
|
||||
fs = (struct lfds611_freelist_state *) lfds611_freelist_state;
|
||||
|
||||
lfds611_freelist_use( fs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_freelist_pop( fs, &fe );
|
||||
lfds611_freelist_push( fs, fe );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,515 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_queue( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"Queue Tests\n"
|
||||
"===========\n" );
|
||||
|
||||
queue_test_enqueuing();
|
||||
queue_test_dequeuing();
|
||||
queue_test_enqueuing_and_dequeuing();
|
||||
queue_test_rapid_enqueuing_and_dequeuing();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void queue_test_enqueuing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct queue_test_enqueuing_state
|
||||
*qtes;
|
||||
|
||||
lfds611_atom_t
|
||||
user_data,
|
||||
thread,
|
||||
count,
|
||||
*per_thread_counters;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 1000000, 1000000 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
/* TRD : create an empty queue with 1,000,000 elements in its freelist
|
||||
then run one thread per CPU
|
||||
where each thread busy-works, enqueuing elements (until there are no more elements)
|
||||
each element's void pointer of user data is (thread number | element number)
|
||||
where element_number is a thread-local counter starting at 0
|
||||
where the thread_number occupies the top byte
|
||||
|
||||
when we're done, we check that all the elements are present
|
||||
and increment on a per-thread basis
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Enqueuing" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_queue_new( &qs, 1000000 );
|
||||
|
||||
qtes = malloc( sizeof(struct queue_test_enqueuing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(qtes+loop)->qs = qs;
|
||||
(qtes+loop)->counter = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_enqueuer, qtes+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
free( qtes );
|
||||
|
||||
/* TRD : first, validate the queue
|
||||
|
||||
then dequeue
|
||||
we expect to find element numbers increment on a per thread basis
|
||||
*/
|
||||
|
||||
lfds611_queue_query( qs, LFDS611_QUEUE_QUERY_VALIDATE, &vi, dvs );
|
||||
|
||||
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
*(per_thread_counters+loop) = 0;
|
||||
|
||||
while( dvs[0] == LFDS611_VALIDITY_VALID and dvs[1] == LFDS611_VALIDITY_VALID and lfds611_queue_dequeue(qs, (void *) &user_data) ) {
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= cpu_count ) {
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if( count < per_thread_counters[thread] )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
if( count > per_thread_counters[thread] )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( count == per_thread_counters[thread] )
|
||||
per_thread_counters[thread]++;
|
||||
}
|
||||
|
||||
free( per_thread_counters );
|
||||
|
||||
lfds611_queue_delete( qs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state )
|
||||
{
|
||||
struct queue_test_enqueuing_state
|
||||
*qtes;
|
||||
|
||||
assert( queue_test_enqueuing_state != NULL );
|
||||
|
||||
qtes = (struct queue_test_enqueuing_state *) queue_test_enqueuing_state;
|
||||
|
||||
lfds611_queue_use( qtes->qs );
|
||||
|
||||
// TRD : top byte of counter is already our thread number
|
||||
while( lfds611_queue_enqueue(qtes->qs, (void *) qtes->counter++) );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void queue_test_dequeuing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct queue_test_dequeuing_state
|
||||
*qtds;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 0, 0 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
/* TRD : create a queue with 1,000,000 elements
|
||||
|
||||
use a single thread to enqueue every element
|
||||
each elements user data is an incrementing counter
|
||||
|
||||
then run one thread per CPU
|
||||
where each busy-works dequeuing
|
||||
|
||||
when an element is dequeued, we check (on a per-thread basis) the
|
||||
value deqeued is greater than the element previously dequeued
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Dequeuing" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_queue_new( &qs, 1000000 );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ )
|
||||
lfds611_queue_enqueue( qs, (void *) (lfds611_atom_t) loop );
|
||||
|
||||
qtds = malloc( sizeof(struct queue_test_dequeuing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(qtds+loop)->qs = qs;
|
||||
(qtds+loop)->error_flag = LOWERED;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_dequeuer, qtds+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : check queue is empty
|
||||
lfds611_queue_query( qs, LFDS611_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
// TRD : check for raised error flags
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
if( (qtds+loop)->error_flag == RAISED )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
free( qtds );
|
||||
|
||||
lfds611_queue_delete( qs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state )
|
||||
{
|
||||
struct queue_test_dequeuing_state
|
||||
*qtds;
|
||||
|
||||
lfds611_atom_t
|
||||
*prev_user_data,
|
||||
*user_data;
|
||||
|
||||
assert( queue_test_dequeuing_state != NULL );
|
||||
|
||||
qtds = (struct queue_test_dequeuing_state *) queue_test_dequeuing_state;
|
||||
|
||||
lfds611_queue_use( qtds->qs );
|
||||
|
||||
lfds611_queue_dequeue( qtds->qs, (void *) &prev_user_data );
|
||||
|
||||
while( lfds611_queue_dequeue(qtds->qs, (void *) &user_data) ) {
|
||||
if( user_data <= prev_user_data )
|
||||
qtds->error_flag = RAISED;
|
||||
|
||||
prev_user_data = user_data;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void queue_test_enqueuing_and_dequeuing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
subloop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct queue_test_enqueuing_and_dequeuing_state
|
||||
*qteds;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 0, 0 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
internal_display_test_name( "Enqueuing and dequeuing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_queue_new( &qs, cpu_count );
|
||||
|
||||
qteds = malloc( sizeof(struct queue_test_enqueuing_and_dequeuing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(qteds+loop)->qs = qs;
|
||||
(qteds+loop)->thread_number = loop;
|
||||
(qteds+loop)->counter = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
(qteds+loop)->cpu_count = cpu_count;
|
||||
(qteds+loop)->error_flag = LOWERED;
|
||||
(qteds+loop)->per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( subloop = 0 ; subloop < cpu_count ; subloop++ )
|
||||
*((qteds+loop)->per_thread_counters+subloop) = 0;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_enqueuer_and_dequeuer, qteds+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
lfds611_queue_query( qs, LFDS611_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
if( (qteds+loop)->error_flag == RAISED )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
free( (qteds+loop)->per_thread_counters );
|
||||
|
||||
free( qteds );
|
||||
|
||||
lfds611_queue_delete( qs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_enqueuing_and_dequeuing_state )
|
||||
{
|
||||
struct queue_test_enqueuing_and_dequeuing_state
|
||||
*qteds;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
lfds611_atom_t
|
||||
thread,
|
||||
count,
|
||||
user_data;
|
||||
|
||||
assert( queue_test_enqueuing_and_dequeuing_state != NULL );
|
||||
|
||||
qteds = (struct queue_test_enqueuing_and_dequeuing_state *) queue_test_enqueuing_and_dequeuing_state;
|
||||
|
||||
lfds611_queue_use( qteds->qs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_queue_enqueue( qteds->qs, (void *) (qteds->counter++) );
|
||||
lfds611_queue_dequeue( qteds->qs, (void *) &user_data );
|
||||
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= qteds->cpu_count )
|
||||
qteds->error_flag = RAISED;
|
||||
else {
|
||||
if( count < qteds->per_thread_counters[thread] )
|
||||
qteds->error_flag = RAISED;
|
||||
|
||||
if( count >= qteds->per_thread_counters[thread] )
|
||||
qteds->per_thread_counters[thread] = count+1;
|
||||
}
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void queue_test_rapid_enqueuing_and_dequeuing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_queue_state
|
||||
*qs;
|
||||
|
||||
struct queue_test_rapid_enqueuing_and_dequeuing_state
|
||||
*qtreds;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 50000, 50000 };
|
||||
|
||||
lfds611_atom_t
|
||||
user_data,
|
||||
thread,
|
||||
count,
|
||||
*per_thread_counters;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
internal_display_test_name( "Rapid enqueuing and dequeuing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_queue_new( &qs, 100000 );
|
||||
|
||||
for( loop = 0 ; loop < 50000 ; loop++ )
|
||||
lfds611_queue_enqueue( qs, NULL );
|
||||
|
||||
qtreds = malloc( sizeof(struct queue_test_rapid_enqueuing_and_dequeuing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(qtreds+loop)->qs = qs;
|
||||
(qtreds+loop)->counter = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_rapid_enqueuer_and_dequeuer, qtreds+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
lfds611_queue_query( qs, LFDS611_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
// TRD : now check results
|
||||
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
*(per_thread_counters+loop) = 0;
|
||||
|
||||
while( dvs[0] == LFDS611_VALIDITY_VALID and dvs[1] == LFDS611_VALIDITY_VALID and lfds611_queue_dequeue(qs, (void *) &user_data) ) {
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= cpu_count ) {
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if( per_thread_counters[thread] == 0 )
|
||||
per_thread_counters[thread] = count;
|
||||
|
||||
if( count < per_thread_counters[thread] )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
if( count >= per_thread_counters[thread] )
|
||||
per_thread_counters[thread] = count+1;
|
||||
}
|
||||
|
||||
free( per_thread_counters );
|
||||
|
||||
free( qtreds );
|
||||
|
||||
lfds611_queue_delete( qs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state )
|
||||
{
|
||||
struct queue_test_rapid_enqueuing_and_dequeuing_state
|
||||
*qtreds;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
lfds611_atom_t
|
||||
user_data;
|
||||
|
||||
assert( queue_test_rapid_enqueuing_and_dequeuing_state != NULL );
|
||||
|
||||
qtreds = (struct queue_test_rapid_enqueuing_and_dequeuing_state *) queue_test_rapid_enqueuing_and_dequeuing_state;
|
||||
|
||||
lfds611_queue_use( qtreds->qs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_queue_enqueue( qtreds->qs, (void *) (qtreds->counter++) );
|
||||
lfds611_queue_dequeue( qtreds->qs, (void *) &user_data );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,472 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_ringbuffer( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"Ringbuffer Tests\n"
|
||||
"================\n" );
|
||||
|
||||
ringbuffer_test_reading();
|
||||
ringbuffer_test_writing();
|
||||
ringbuffer_test_reading_and_writing();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void ringbuffer_test_reading( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
struct ringbuffer_test_reading_state
|
||||
*rtrs;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 0, 0 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[3];
|
||||
|
||||
lfds611_atom_t
|
||||
total_read = 0;
|
||||
|
||||
/* TRD : we create a single ringbuffer
|
||||
with 1,000,000 elements
|
||||
we populate the ringbuffer, where the
|
||||
user data is an incrementing counter
|
||||
|
||||
we create one thread per CPU
|
||||
where each thread busy-works,
|
||||
reading until the ringbuffer is empty
|
||||
|
||||
each thread keeps track of the number of reads it manages
|
||||
and that each user data it reads is greater than the
|
||||
previous user data that was read
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Reading" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_ringbuffer_new( &rs, 1000000, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ ) {
|
||||
lfds611_ringbuffer_get_write_element( rs, &fe, NULL );
|
||||
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) loop );
|
||||
lfds611_ringbuffer_put_write_element( rs, fe );
|
||||
}
|
||||
|
||||
rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(rtrs+loop)->rs = rs;
|
||||
(rtrs+loop)->read_count = 0;
|
||||
(rtrs+loop)->error_flag = LOWERED;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
// TRD : check for raised error flags
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
if( (rtrs+loop)->error_flag == RAISED )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
// TRD : check thread reads total to 1,000,000
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
total_read += (rtrs+loop)->read_count;
|
||||
|
||||
if( total_read < 1000000 )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( total_read > 1000000 )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
free( rtrs );
|
||||
|
||||
lfds611_ringbuffer_delete( rs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
|
||||
{
|
||||
struct ringbuffer_test_reading_state
|
||||
*rtrs;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
lfds611_atom_t
|
||||
*prev_user_data,
|
||||
*user_data;
|
||||
|
||||
assert( ringbuffer_test_reading_state != NULL );
|
||||
|
||||
rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
|
||||
|
||||
lfds611_ringbuffer_use( rtrs->rs );
|
||||
|
||||
/* TRD : read an initial element to load a value into prev_user_data
|
||||
it may be (under valgrind for example) that by the time we start
|
||||
there are no elements remaining to read
|
||||
*/
|
||||
|
||||
lfds611_ringbuffer_get_read_element( rtrs->rs, &fe );
|
||||
|
||||
if( fe == NULL )
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
|
||||
lfds611_ringbuffer_put_read_element( rtrs->rs, fe );
|
||||
|
||||
rtrs->read_count++;
|
||||
|
||||
while( lfds611_ringbuffer_get_read_element(rtrs->rs, &fe) ) {
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void **) &user_data );
|
||||
lfds611_ringbuffer_put_read_element( rtrs->rs, fe );
|
||||
|
||||
if( user_data <= prev_user_data )
|
||||
rtrs->error_flag = RAISED;
|
||||
|
||||
prev_user_data = user_data;
|
||||
|
||||
rtrs->read_count++;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void ringbuffer_test_writing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
struct ringbuffer_test_writing_state
|
||||
*rtws;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 100000, 100000 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[3];
|
||||
|
||||
lfds611_atom_t
|
||||
thread,
|
||||
count,
|
||||
user_data,
|
||||
*per_thread_counters;
|
||||
|
||||
/* TRD : we create a single ringbuffer
|
||||
with 100000 elements
|
||||
the ringbuffers starts empty
|
||||
|
||||
we create one thread per CPU
|
||||
where each thread busy-works writing
|
||||
for ten seconds
|
||||
|
||||
the user data in each written element is a combination
|
||||
of the thread number and the counter
|
||||
|
||||
after the threads are complete, we validate by
|
||||
checking the user data counters increment on a per thread
|
||||
basis
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Writing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_ringbuffer_new( &rs, 100000, NULL, NULL );
|
||||
|
||||
rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(rtws+loop)->rs = rs;
|
||||
(rtws+loop)->write_count = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : now check results
|
||||
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
*(per_thread_counters+loop) = 0;
|
||||
|
||||
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
while( dvs[0] == LFDS611_VALIDITY_VALID and dvs[1] == LFDS611_VALIDITY_VALID and dvs[2] == LFDS611_VALIDITY_VALID and lfds611_ringbuffer_get_read_element(rs, &fe) ) {
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void *) &user_data );
|
||||
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= cpu_count ) {
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
lfds611_ringbuffer_put_read_element( rs, fe );
|
||||
break;
|
||||
}
|
||||
|
||||
if( per_thread_counters[thread] == 0 )
|
||||
per_thread_counters[thread] = count;
|
||||
|
||||
if( count < per_thread_counters[thread] )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
if( count >= per_thread_counters[thread] )
|
||||
per_thread_counters[thread] = count+1;
|
||||
|
||||
lfds611_ringbuffer_put_read_element( rs, fe );
|
||||
}
|
||||
|
||||
free( per_thread_counters );
|
||||
|
||||
free( rtws );
|
||||
|
||||
lfds611_ringbuffer_delete( rs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
|
||||
{
|
||||
struct ringbuffer_test_writing_state
|
||||
*rtws;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( ringbuffer_test_writing_state != NULL );
|
||||
|
||||
rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
|
||||
|
||||
lfds611_ringbuffer_use( rtws->rs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
|
||||
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) (rtws->write_count++) );
|
||||
lfds611_ringbuffer_put_write_element( rtws->rs, fe );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void ringbuffer_test_reading_and_writing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
subloop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_ringbuffer_state
|
||||
*rs;
|
||||
|
||||
struct ringbuffer_test_reading_and_writing_state
|
||||
*rtrws;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 0, 0 };
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[3];
|
||||
|
||||
/* TRD : we create a single ringbuffer
|
||||
with 100000 elements
|
||||
the ringbuffers starts empty
|
||||
|
||||
we create one thread per CPU
|
||||
where each thread busy-works writing
|
||||
and then immediately reading
|
||||
for ten seconds
|
||||
|
||||
the user data in each written element is a combination
|
||||
of the thread number and the counter
|
||||
|
||||
while a thread runs, it keeps track of the
|
||||
counters for the other threads and throws an error
|
||||
if it sees the number stay the same or decrease
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Reading and writing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_ringbuffer_new( &rs, 100000, NULL, NULL );
|
||||
|
||||
rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(rtrws+loop)->rs = rs;
|
||||
(rtrws+loop)->counter = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
(rtrws+loop)->cpu_count = cpu_count;
|
||||
(rtrws+loop)->error_flag = LOWERED;
|
||||
(rtrws+loop)->per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( subloop = 0 ; subloop < cpu_count ; subloop++ )
|
||||
*((rtrws+loop)->per_thread_counters+subloop) = 0;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
if( (rtrws+loop)->error_flag == RAISED )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
free( (rtrws+loop)->per_thread_counters );
|
||||
|
||||
free( rtrws );
|
||||
|
||||
lfds611_ringbuffer_delete( rs, NULL, NULL );
|
||||
|
||||
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
|
||||
{
|
||||
struct ringbuffer_test_reading_and_writing_state
|
||||
*rtrws;
|
||||
|
||||
struct lfds611_freelist_element
|
||||
*fe;
|
||||
|
||||
lfds611_atom_t
|
||||
user_data,
|
||||
thread,
|
||||
count;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( ringbuffer_test_reading_and_writing_state != NULL );
|
||||
|
||||
rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
|
||||
|
||||
lfds611_ringbuffer_use( rtrws->rs );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
|
||||
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) (rtrws->counter++) );
|
||||
lfds611_ringbuffer_put_write_element( rtrws->rs, fe );
|
||||
|
||||
lfds611_ringbuffer_get_read_element( rtrws->rs, &fe );
|
||||
lfds611_freelist_get_user_data_from_element( fe, (void *) &user_data );
|
||||
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= rtrws->cpu_count )
|
||||
rtrws->error_flag = RAISED;
|
||||
else {
|
||||
if( count < rtrws->per_thread_counters[thread] )
|
||||
rtrws->error_flag = RAISED;
|
||||
|
||||
if( count >= rtrws->per_thread_counters[thread] )
|
||||
rtrws->per_thread_counters[thread] = count+1;
|
||||
}
|
||||
|
||||
lfds611_ringbuffer_put_read_element( rtrws->rs, fe );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_slist( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"SList Tests\n"
|
||||
"===========\n" );
|
||||
|
||||
test_slist_new_delete_get();
|
||||
test_slist_get_set_user_data();
|
||||
test_slist_delete_all_elements();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_slist_new_delete_get( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_slist_state
|
||||
*ss;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
struct slist_test_state
|
||||
*sts;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
size_t
|
||||
total_create_count = 0,
|
||||
total_delete_count = 0,
|
||||
element_count = 0;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs = LFDS611_VALIDITY_VALID;
|
||||
|
||||
/* TRD : two threads per CPU
|
||||
first simply alternates between new_head() and new_next() (next on element created by head)
|
||||
second calls get_next, if NULL, then calls get_head, and deletes the element
|
||||
both threads keep count of created and deleted
|
||||
validate is to reconcile created, deleted and remaining in list
|
||||
*/
|
||||
|
||||
internal_display_test_name( "New head/next, delete and get next" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_slist_new( &ss, NULL, NULL );
|
||||
|
||||
sts = malloc( sizeof(struct slist_test_state) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) {
|
||||
(sts+loop)->ss = ss;
|
||||
(sts+loop)->create_count = 0;
|
||||
(sts+loop)->delete_count = 0;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
abstraction_thread_start( &thread_handles[loop], loop, slist_test_internal_thread_new_delete_get_new_head_and_next, sts+loop );
|
||||
abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_test_internal_thread_new_delete_get_delete_and_get, sts+loop+cpu_count );
|
||||
}
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : now validate
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) {
|
||||
total_create_count += (sts+loop)->create_count;
|
||||
total_delete_count += (sts+loop)->delete_count;
|
||||
}
|
||||
|
||||
while( NULL != lfds611_slist_get_head_and_then_next(ss, &se) )
|
||||
element_count++;
|
||||
|
||||
if( total_create_count - total_delete_count - element_count != 0 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
free( sts );
|
||||
|
||||
lfds611_slist_delete( ss );
|
||||
|
||||
internal_display_test_result( 1, "slist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_new_head_and_next( void *slist_test_state )
|
||||
{
|
||||
struct slist_test_state
|
||||
*sts;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
assert( slist_test_state != NULL );
|
||||
|
||||
sts = (struct slist_test_state *) slist_test_state;
|
||||
|
||||
lfds611_slist_use( sts->ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 1 ) {
|
||||
if( sts->create_count % 2 == 0 )
|
||||
se = lfds611_slist_new_head( sts->ss, NULL );
|
||||
else
|
||||
lfds611_slist_new_next( se, NULL );
|
||||
|
||||
sts->create_count++;
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_delete_and_get( void *slist_test_state )
|
||||
{
|
||||
struct slist_test_state
|
||||
*sts;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
assert( slist_test_state != NULL );
|
||||
|
||||
sts = (struct slist_test_state *) slist_test_state;
|
||||
|
||||
lfds611_slist_use( sts->ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 1 ) {
|
||||
if( se == NULL )
|
||||
lfds611_slist_get_head( sts->ss, &se );
|
||||
else
|
||||
lfds611_slist_get_next( se, &se );
|
||||
|
||||
if( se != NULL ) {
|
||||
if( 1 == lfds611_slist_logically_delete_element(sts->ss, se) )
|
||||
sts->delete_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_slist_get_set_user_data( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
struct lfds611_slist_state
|
||||
*ss;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
struct slist_test_state
|
||||
*sts;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
lfds611_atom_t
|
||||
thread_and_count,
|
||||
thread,
|
||||
count,
|
||||
*per_thread_counters,
|
||||
*per_thread_drop_flags;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs = LFDS611_VALIDITY_VALID;
|
||||
|
||||
/* TRD : create a list of (cpu_count*10) elements, user data 0
|
||||
one thread per CPU
|
||||
each thread loops, setting user_data to ((thread_number << (sizeof(lfds611_atom_t)*8-8)) | count)
|
||||
validation is to scan list, count on a per thread basis should go down only once
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Get and set user data" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_slist_new( &ss, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 10 ; loop++ )
|
||||
lfds611_slist_new_head( ss, NULL );
|
||||
|
||||
sts = malloc( sizeof(struct slist_test_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(sts+loop)->ss = ss;
|
||||
(sts+loop)->thread_and_count = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, slist_test_internal_thread_get_set_user_data, sts+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// now validate
|
||||
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
per_thread_drop_flags = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
*(per_thread_counters+loop) = 0;
|
||||
*(per_thread_drop_flags+loop) = 0;
|
||||
}
|
||||
|
||||
while( dvs == LFDS611_VALIDITY_VALID and NULL != lfds611_slist_get_head_and_then_next(ss, &se) ) {
|
||||
lfds611_slist_get_user_data_from_element( se, (void **) &thread_and_count );
|
||||
|
||||
thread = thread_and_count >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (thread_and_count << 8) >> 8;
|
||||
|
||||
if( thread >= cpu_count ) {
|
||||
dvs = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if( per_thread_counters[thread] == 0 ) {
|
||||
per_thread_counters[thread] = count;
|
||||
continue;
|
||||
}
|
||||
|
||||
per_thread_counters[thread]++;
|
||||
|
||||
if( count < per_thread_counters[thread] and per_thread_drop_flags[thread] == 1 ) {
|
||||
dvs = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
break;
|
||||
}
|
||||
|
||||
if( count < per_thread_counters[thread] and per_thread_drop_flags[thread] == 0 ) {
|
||||
per_thread_drop_flags[thread] = 1;
|
||||
per_thread_counters[thread] = count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( count < per_thread_counters[thread] )
|
||||
dvs = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
if( count >= per_thread_counters[thread] )
|
||||
per_thread_counters[thread] = count;
|
||||
}
|
||||
|
||||
free( per_thread_drop_flags );
|
||||
free( per_thread_counters );
|
||||
|
||||
free( sts );
|
||||
|
||||
lfds611_slist_delete( ss );
|
||||
|
||||
internal_display_test_result( 1, "slist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION slist_test_internal_thread_get_set_user_data( void *slist_test_state )
|
||||
{
|
||||
struct slist_test_state
|
||||
*sts;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
assert( slist_test_state != NULL );
|
||||
|
||||
sts = (struct slist_test_state *) slist_test_state;
|
||||
|
||||
lfds611_slist_use( sts->ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 1 ) {
|
||||
if( se == NULL )
|
||||
lfds611_slist_get_head( sts->ss, &se );
|
||||
|
||||
lfds611_slist_set_user_data_in_element( se, (void *) sts->thread_and_count++ );
|
||||
|
||||
lfds611_slist_get_next( se, &se );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_slist_delete_all_elements( void )
|
||||
{
|
||||
struct lfds611_slist_state
|
||||
*ss;
|
||||
|
||||
struct lfds611_slist_element
|
||||
*se = NULL;
|
||||
|
||||
size_t
|
||||
element_count = 0;
|
||||
|
||||
unsigned int
|
||||
loop;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs = LFDS611_VALIDITY_VALID;
|
||||
|
||||
/* TRD : this test creates a list of 100,000 elements
|
||||
then simply calls delete_all_elements()
|
||||
we then count the number of elements remaining
|
||||
should be zero :-)
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Delete all elements" );
|
||||
|
||||
lfds611_slist_new( &ss, NULL, NULL );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ )
|
||||
lfds611_slist_new_head( ss, NULL );
|
||||
|
||||
lfds611_slist_single_threaded_physically_delete_all_elements( ss );
|
||||
|
||||
while( NULL != lfds611_slist_get_head_and_then_next(ss, &se) )
|
||||
element_count++;
|
||||
|
||||
if( element_count != 0 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
|
||||
lfds611_slist_delete( ss );
|
||||
|
||||
internal_display_test_result( 1, "slist", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,582 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void test_lfds611_stack( void )
|
||||
{
|
||||
printf( "\n"
|
||||
"Stack Tests\n"
|
||||
"===========\n" );
|
||||
|
||||
stack_test_internal_popping();
|
||||
stack_test_internal_pushing();
|
||||
stack_test_internal_popping_and_pushing();
|
||||
stack_test_internal_rapid_popping_and_pushing();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void stack_test_internal_popping( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
*found_count,
|
||||
cpu_count;
|
||||
|
||||
lfds611_atom_t
|
||||
count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs = LFDS611_VALIDITY_VALID;
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
struct stack_test_popping_state
|
||||
*stps;
|
||||
|
||||
/* TRD : we create a stack with 1,000,000 elements
|
||||
|
||||
we then populate the stack, where each element is
|
||||
set to contain a void pointer which is its element number
|
||||
|
||||
we then run one thread per CPU
|
||||
where each thread loops, popping as quickly as possible
|
||||
each popped element is pushed onto a thread-local stack
|
||||
|
||||
the threads run till the source stack is empty
|
||||
|
||||
we then check the thread-local stacks
|
||||
we should find we have every element
|
||||
|
||||
then tidy up
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Popping" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_stack_new( &ss, 1000000 );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ )
|
||||
lfds611_stack_push( ss, (void *) (lfds611_atom_t) loop );
|
||||
|
||||
stps = malloc( sizeof(struct stack_test_popping_state) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(stps+loop)->ss = ss;
|
||||
lfds611_stack_new( &(stps+loop)->ss_thread_local, 1000000 );
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_popping, stps+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : now we check the thread-local stacks
|
||||
found_count = malloc( sizeof(unsigned int) * 1000000 );
|
||||
|
||||
for( loop = 0 ; loop < 1000000 ; loop++ )
|
||||
*(found_count+loop) = 0;
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
while( lfds611_stack_pop((stps+loop)->ss_thread_local, (void **) &count) )
|
||||
(*(found_count+count))++;
|
||||
|
||||
for( loop = 0 ; loop < 1000000 and dvs == LFDS611_VALIDITY_VALID ; loop++ ) {
|
||||
if( *(found_count+loop) == 0 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
|
||||
|
||||
if( *(found_count+loop) > 1 )
|
||||
dvs = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
}
|
||||
|
||||
// TRD : cleanup
|
||||
free( found_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
lfds611_stack_delete( (stps+loop)->ss_thread_local, NULL, NULL );
|
||||
|
||||
free( stps );
|
||||
lfds611_stack_delete( ss, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 1, "stack", dvs );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping( void *stack_test_popping_state )
|
||||
{
|
||||
struct stack_test_popping_state
|
||||
*stps;
|
||||
|
||||
lfds611_atom_t
|
||||
count;
|
||||
|
||||
assert( stack_test_popping_state != NULL );
|
||||
|
||||
stps = (struct stack_test_popping_state *) stack_test_popping_state;
|
||||
|
||||
lfds611_stack_use( stps->ss );
|
||||
|
||||
while( lfds611_stack_pop(stps->ss, (void **) &count) )
|
||||
lfds611_stack_push( stps->ss_thread_local, (void *) count );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void stack_test_internal_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
struct stack_test_pushing_state
|
||||
*stps;
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
lfds611_atom_t
|
||||
user_data,
|
||||
thread,
|
||||
count,
|
||||
*per_thread_counters;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi = { 1000000, 1000000 };
|
||||
|
||||
/* TRD : we create a stack with 1,000,000 elements
|
||||
|
||||
we then create one thread per CPU, where each thread
|
||||
pushes as quickly as possible to the stack
|
||||
|
||||
the data pushed is a counter and a thread ID
|
||||
|
||||
the threads exit when the stack is full
|
||||
|
||||
we then validate the stack;
|
||||
|
||||
checking that the counts increment on a per unique ID basis
|
||||
and that the number of elements we pop equals 1,000,000
|
||||
(since each element has an incrementing counter which is
|
||||
unique on a per unique ID basis, we can know we didn't lose
|
||||
any elements)
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Pushing" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
stps = malloc( sizeof(struct stack_test_pushing_state) * cpu_count );
|
||||
|
||||
// TRD : the main stack
|
||||
lfds611_stack_new( &ss, 1000000 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(stps+loop)->thread_number = (lfds611_atom_t) loop;
|
||||
(stps+loop)->ss = ss;
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_pushing, stps+loop );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
// TRD : the stack is now fully pushed; time to verify
|
||||
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
*(per_thread_counters+loop) = 1000000;
|
||||
|
||||
lfds611_stack_query( ss, LFDS611_STACK_QUERY_VALIDATE, &vi, (void *) dvs );
|
||||
|
||||
while( dvs[0] == LFDS611_VALIDITY_VALID and lfds611_stack_pop(ss, (void **) &user_data) ) {
|
||||
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
|
||||
count = (user_data << 8) >> 8;
|
||||
|
||||
if( thread >= cpu_count ) {
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if( count > per_thread_counters[thread] )
|
||||
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
|
||||
|
||||
if( count < per_thread_counters[thread] )
|
||||
per_thread_counters[thread] = count-1;
|
||||
}
|
||||
|
||||
// TRD : clean up
|
||||
free( per_thread_counters );
|
||||
|
||||
free( stps );
|
||||
|
||||
lfds611_stack_delete( ss, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_pushing( void *stack_test_pushing_state )
|
||||
{
|
||||
struct stack_test_pushing_state
|
||||
*stps;
|
||||
|
||||
lfds611_atom_t
|
||||
counter = 0;
|
||||
|
||||
assert( stack_test_pushing_state != NULL );
|
||||
|
||||
stps = (struct stack_test_pushing_state *) stack_test_pushing_state;
|
||||
|
||||
lfds611_stack_use( stps->ss );
|
||||
|
||||
// TRD : we write (thread_number | counter), where thread_number is the top 8 bits of the lfds611_atom_t
|
||||
while( lfds611_stack_push(stps->ss, (void **) ((stps->thread_number << (sizeof(lfds611_atom_t)*8-8)) | counter++)) );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void stack_test_internal_popping_and_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
subloop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
struct stack_test_popping_and_pushing_state
|
||||
*stpps;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi;
|
||||
|
||||
/* TRD : we have two threads per CPU
|
||||
the threads loop for ten seconds
|
||||
the first thread pushes 100000 elements then pops 100000 elements
|
||||
the second thread pops 100000 elements then pushes 100000 elements
|
||||
all pushes and pops go onto the single main stack
|
||||
|
||||
after time is up, all threads push what they have remaining onto
|
||||
the main stack
|
||||
|
||||
we then validate the main stack
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Popping and pushing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
// TRD : just some initial elements so the pushing threads can start immediately
|
||||
lfds611_stack_new( &ss, 100000 * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < 100000 * cpu_count ; loop++ )
|
||||
lfds611_stack_push( ss, (void *) (lfds611_atom_t) loop );
|
||||
|
||||
stpps = malloc( sizeof(struct stack_test_popping_and_pushing_state) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
(stpps+loop)->ss = ss;
|
||||
lfds611_stack_new( &(stpps+loop)->local_ss, 100000 );
|
||||
|
||||
(stpps+loop+cpu_count)->ss = ss;
|
||||
lfds611_stack_new( &(stpps+loop+cpu_count)->local_ss, 100000 );
|
||||
|
||||
// TRD : fill the pushing thread stacks
|
||||
for( subloop = 0 ; subloop < 100000 ; subloop++ )
|
||||
lfds611_stack_push( (stpps+loop+cpu_count)->local_ss, (void *) (lfds611_atom_t) subloop );
|
||||
}
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ ) {
|
||||
abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_popping_and_pushing_start_popping, stpps+loop );
|
||||
abstraction_thread_start( &thread_handles[loop+cpu_count], loop, stack_test_internal_thread_popping_and_pushing_start_pushing, stpps+loop+cpu_count );
|
||||
}
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
|
||||
lfds611_stack_delete( (stpps+loop)->local_ss, NULL, NULL );
|
||||
|
||||
free( stpps );
|
||||
|
||||
vi.min_elements = vi.max_elements = 100000 * cpu_count * 2;
|
||||
|
||||
lfds611_stack_query( ss, LFDS611_STACK_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
lfds611_stack_delete( ss, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_popping( void *stack_test_popping_and_pushing_state )
|
||||
{
|
||||
struct stack_test_popping_and_pushing_state
|
||||
*stpps;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
unsigned int
|
||||
count;
|
||||
|
||||
assert( stack_test_popping_and_pushing_state != NULL );
|
||||
|
||||
stpps = (struct stack_test_popping_and_pushing_state *) stack_test_popping_and_pushing_state;
|
||||
|
||||
lfds611_stack_use( stpps->ss );
|
||||
lfds611_stack_use( stpps->local_ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
count = 0;
|
||||
|
||||
while( count < 100000 )
|
||||
if( lfds611_stack_pop(stpps->ss, &user_data) ) {
|
||||
lfds611_stack_push( stpps->local_ss, user_data );
|
||||
count++;
|
||||
}
|
||||
|
||||
// TRD : return our local stack to the main stack
|
||||
while( lfds611_stack_pop(stpps->local_ss, &user_data) )
|
||||
lfds611_stack_push( stpps->ss, user_data );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_pushing( void *stack_test_popping_and_pushing_state )
|
||||
{
|
||||
struct stack_test_popping_and_pushing_state
|
||||
*stpps;
|
||||
|
||||
void
|
||||
*user_data;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
unsigned int
|
||||
count;
|
||||
|
||||
assert( stack_test_popping_and_pushing_state != NULL );
|
||||
|
||||
stpps = (struct stack_test_popping_and_pushing_state *) stack_test_popping_and_pushing_state;
|
||||
|
||||
lfds611_stack_use( stpps->ss );
|
||||
lfds611_stack_use( stpps->local_ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
// TRD : return our local stack to the main stack
|
||||
while( lfds611_stack_pop(stpps->local_ss, &user_data) )
|
||||
lfds611_stack_push( stpps->ss, user_data );
|
||||
|
||||
count = 0;
|
||||
|
||||
while( count < 100000 )
|
||||
if( lfds611_stack_pop(stpps->ss, &user_data) ) {
|
||||
lfds611_stack_push( stpps->local_ss, user_data );
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// TRD : now push whatever we have in our local stack
|
||||
while( lfds611_stack_pop(stpps->local_ss, &user_data) )
|
||||
lfds611_stack_push( stpps->ss, user_data );
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
void stack_test_internal_rapid_popping_and_pushing( void )
|
||||
{
|
||||
unsigned int
|
||||
loop,
|
||||
cpu_count;
|
||||
|
||||
thread_state_t
|
||||
*thread_handles;
|
||||
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
struct lfds611_validation_info
|
||||
vi;
|
||||
|
||||
enum lfds611_data_structure_validity
|
||||
dvs[2];
|
||||
|
||||
/* TRD : in these tests there is a fundamental antagonism between
|
||||
how much checking/memory clean up that we do and the
|
||||
likelyhood of collisions between threads in their lock-free
|
||||
operations
|
||||
|
||||
the lock-free operations are very quick; if we do anything
|
||||
much at all between operations, we greatly reduce the chance
|
||||
of threads colliding
|
||||
|
||||
so we have some tests which do enough checking/clean up that
|
||||
they can tell the stack is valid and don't leak memory
|
||||
and here, this test now is one of those which does minimal
|
||||
checking - in fact, the nature of the test is that you can't
|
||||
do any real checking - but goes very quickly
|
||||
|
||||
what we do is create a small stack and then run one thread
|
||||
per CPU, where each thread simply pushes and then immediately
|
||||
pops
|
||||
|
||||
the test runs for ten seconds
|
||||
|
||||
after the test is done, the only check we do is to traverse
|
||||
the stack, checking for loops and ensuring the number of
|
||||
elements is correct
|
||||
*/
|
||||
|
||||
internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
|
||||
|
||||
cpu_count = abstraction_cpu_count();
|
||||
|
||||
lfds611_stack_new( &ss, cpu_count );
|
||||
|
||||
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_rapid_popping_and_pushing, ss );
|
||||
|
||||
for( loop = 0 ; loop < cpu_count ; loop++ )
|
||||
abstraction_thread_wait( thread_handles[loop] );
|
||||
|
||||
free( thread_handles );
|
||||
|
||||
vi.min_elements = 0;
|
||||
vi.max_elements = 0;
|
||||
|
||||
lfds611_stack_query( ss, LFDS611_STACK_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
|
||||
|
||||
lfds611_stack_delete( ss, NULL, NULL );
|
||||
|
||||
// TRD : print the test result
|
||||
internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
thread_return_t CALLING_CONVENTION stack_test_internal_thread_rapid_popping_and_pushing( void *stack_state )
|
||||
{
|
||||
struct lfds611_stack_state
|
||||
*ss;
|
||||
|
||||
void
|
||||
*user_data = NULL;
|
||||
|
||||
time_t
|
||||
start_time;
|
||||
|
||||
assert( stack_state != NULL );
|
||||
|
||||
ss = (struct lfds611_stack_state *) stack_state;
|
||||
|
||||
lfds611_stack_use( ss );
|
||||
|
||||
time( &start_time );
|
||||
|
||||
while( time(NULL) < start_time + 10 ) {
|
||||
lfds611_stack_push( ss, user_data );
|
||||
lfds611_stack_pop( ss, &user_data );
|
||||
}
|
||||
|
||||
return( (thread_return_t) EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} = {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds611", "..\liblfds611\liblfds611.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug DLL|Win32 = Debug DLL|Win32
|
||||
Debug DLL|x64 = Debug DLL|x64
|
||||
Debug Lib|Win32 = Debug Lib|Win32
|
||||
Debug Lib|x64 = Debug Lib|x64
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release DLL|Win32 = Release DLL|Win32
|
||||
Release DLL|x64 = Release DLL|x64
|
||||
Release Lib|Win32 = Release Lib|Win32
|
||||
Release Lib|x64 = Release Lib|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.ActiveCfg = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.Build.0 = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.ActiveCfg = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.Build.0 = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.ActiveCfg = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.Build.0 = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.ActiveCfg = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.Build.0 = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.Build.0 = Debug|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.ActiveCfg = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.Build.0 = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.ActiveCfg = Release|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.Build.0 = Release|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.ActiveCfg = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.Build.0 = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.ActiveCfg = Release|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.Build.0 = Release|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.Build.0 = Release|Win32
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.ActiveCfg = Release|x64
|
||||
{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.Build.0 = Release|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.ActiveCfg = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.Build.0 = Debug Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.ActiveCfg = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.Build.0 = Debug Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.ActiveCfg = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.Build.0 = Release Lib|Win32
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.ActiveCfg = Release Lib|x64
|
||||
{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.Build.0 = Release Lib|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,415 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="test"
|
||||
ProjectGUID="{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}"
|
||||
RootNamespace="test"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG /D_CRT_SECURE_NO_WARNINGS"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\..\liblfds611\inc""
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libcmtd.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG /D_CRT_SECURE_NO_WARNINGS"
|
||||
Optimization="0"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\..\liblfds611\inc""
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="1"
|
||||
EnableFunctionLevelLinking="true"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libcmtd.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG /D_CRT_SECURE_NO_WARNINGS"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\..\liblfds611\inc""
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libcmt.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG /D_CRT_SECURE_NO_WARNINGS"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\src";"$(ProjectDir)\..\liblfds611\inc""
|
||||
ExceptionHandling="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="4"
|
||||
WarnAsError="true"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libcmt.lib"
|
||||
IgnoreAllDefaultLibraries="true"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\abstraction.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\abstraction_cpu_count.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\abstraction_thread_start.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\abstraction_thread_wait.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\benchmark_freelist.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\benchmark_queue.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\benchmark_ringbuffer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\benchmark_stack.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\main.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\misc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\structures.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_abstraction.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_freelist.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_queue.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_ringbuffer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_slist.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\test_stack.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Reference in New Issue
Block a user