Merge remote-tracking branch 'origin/develop' into episys-throughput-updates-and-downlink-siso-cm
This commit is contained in:
@@ -21,6 +21,15 @@
|
||||
|
||||
# OpenAirInterface License #
|
||||
|
||||
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
|
||||
* [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
|
||||
|
||||
It is distributed under **OAI Public License V1.1**.
|
||||
|
||||
The license information is distributed under [LICENSE](LICENSE) file in the same directory.
|
||||
|
||||
Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
|
||||
|
||||
# Where to Start #
|
||||
|
||||
* [The implemented features](./doc/FEATURE_SET.md)
|
||||
|
||||
@@ -84,17 +84,8 @@ gNBs =
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPcontrolResourceSetZero = 11;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
#pdsch-ConfigCommon
|
||||
#pdschTimeDomainAllocationList (up to 16 entries)
|
||||
initialDLBWPk0_0 = 0; #for DL slot
|
||||
initialDLBWPmappingType_0 = 0; #0=typeA,1=typeB
|
||||
initialDLBWPstartSymbolAndLength_0 = 40; #this is SS=1,L=13
|
||||
|
||||
initialDLBWPk0_1 = 0; #for mixed slot
|
||||
initialDLBWPmappingType_1 = 0;
|
||||
initialDLBWPstartSymbolAndLength_1 = 57; #this is SS=1,L=5
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
@@ -149,19 +140,6 @@ gNBs =
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
# pusch-ConfigCommon (up to 16 elements)
|
||||
initialULBWPk2_0 = 6; # used for UL slot
|
||||
initialULBWPmappingType_0 = 1
|
||||
initialULBWPstartSymbolAndLength_0 = 41; # this is SS=0 L=13
|
||||
|
||||
initialULBWPk2_1 = 6; # used for mixed slot
|
||||
initialULBWPmappingType_1 = 1;
|
||||
initialULBWPstartSymbolAndLength_1 = 52; # this is SS=10 L=4
|
||||
|
||||
initialULBWPk2_2 = 7; # used for Msg.3 during RA
|
||||
initialULBWPmappingType_2 = 1;
|
||||
initialULBWPstartSymbolAndLength_2 = 52; # this is SS=10 L=4
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
|
||||
@@ -76,17 +76,8 @@ gNBs =
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPcontrolResourceSetZero = 11;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
#pdsch-ConfigCommon
|
||||
#pdschTimeDomainAllocationList (up to 16 entries)
|
||||
initialDLBWPk0_0 = 0; #for DL slot
|
||||
initialDLBWPmappingType_0 = 0; #0=typeA,1=typeB
|
||||
initialDLBWPstartSymbolAndLength_0 = 40; #this is SS=1,L=13
|
||||
|
||||
initialDLBWPk0_1 = 0; #for mixed slot
|
||||
initialDLBWPmappingType_1 = 0;
|
||||
initialDLBWPstartSymbolAndLength_1 = 57; #this is SS=1,L=5
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
@@ -141,19 +132,6 @@ gNBs =
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
# pusch-ConfigCommon (up to 16 elements)
|
||||
initialULBWPk2_0 = 6; # used for UL slot
|
||||
initialULBWPmappingType_0 = 1
|
||||
initialULBWPstartSymbolAndLength_0 = 41; # this is SS=0 L=13
|
||||
|
||||
initialULBWPk2_1 = 6; # used for mixed slot
|
||||
initialULBWPmappingType_1 = 1;
|
||||
initialULBWPstartSymbolAndLength_1 = 52; # this is SS=10 L=4
|
||||
|
||||
initialULBWPk2_2 = 7; # used for Msg.3 during RA
|
||||
initialULBWPmappingType_2 = 1;
|
||||
initialULBWPstartSymbolAndLength_2 = 52; # this is SS=10 L=4
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
|
||||
@@ -997,8 +997,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")
|
||||
@@ -1013,8 +1011,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)
|
||||
|
||||
@@ -1062,6 +1081,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})
|
||||
@@ -1073,6 +1095,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
|
||||
@@ -1095,7 +1118,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
|
||||
@@ -1159,6 +1184,10 @@ 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
|
||||
@@ -1781,7 +1810,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
|
||||
@@ -1836,7 +1864,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
|
||||
@@ -2377,43 +2404,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
|
||||
@@ -2603,8 +2593,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})
|
||||
@@ -2643,8 +2633,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_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB})
|
||||
|
||||
@@ -2701,8 +2691,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})
|
||||
@@ -2740,8 +2730,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)
|
||||
@@ -2780,11 +2770,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})
|
||||
@@ -2812,7 +2802,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}
|
||||
)
|
||||
|
||||
@@ -2976,7 +2966,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
|
||||
)
|
||||
|
||||
@@ -2998,7 +2988,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)
|
||||
|
||||
@@ -3019,12 +3009,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)
|
||||
@@ -3128,8 +3118,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
|
||||
|
||||
@@ -346,7 +346,7 @@ typedef struct {
|
||||
@param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
|
||||
@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1)
|
||||
*/
|
||||
#define MATLAB_RAW (1<<31)
|
||||
#define MATLAB_RAW (1U<<31)
|
||||
#define MATLAB_SHORT 0
|
||||
#define MATLAB_CSHORT 1
|
||||
#define MATLAB_INT 2
|
||||
|
||||
@@ -18,6 +18,10 @@ The UE executable is able to "simulate" multiple UEs in order to stimulate the s
|
||||
|
||||
**This simulator is available starting the `v1.0.0` release on the `master` branch.**
|
||||
|
||||
**2022/03/08: CAUTION, THIS TUTORIAL IS NO LONGER VALID on the `develop` branch after the `2022.w01` tag.**
|
||||
|
||||
**2022/03/08: CAUTION, THE LAST VALID TAG on `develop` branch is `2021.w51_c`.**
|
||||
|
||||
Currently the Continuous Integration process is validating this simulator the following way:
|
||||
|
||||
* the LTE modem executable is run on one host (in our CI deployment it is a **Xenial Virtual Machine**)
|
||||
@@ -31,6 +35,17 @@ Normally it should be fine to run both executables on the same host using the `l
|
||||
1. [With S1 -- eNB and UE on 2 hosts](L2NFAPI_S1.md)
|
||||
2. [No S1 -- eNB and UE on 2 hosts](L2NFAPI_NOS1.md)
|
||||
|
||||
|
||||
**2022/03/08: Starting the `2022.w01` tag on the `develop` branch, the L2 nFAPI simulation is using a proxy.**
|
||||
|
||||
A tutorial is available on the [EpiSci GitHub Repository](https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy#readme).
|
||||
|
||||
This proxy allows to perform L2 nFAPI simulator for:
|
||||
|
||||
* LTE
|
||||
* 5G-NSA
|
||||
* 5G-SA
|
||||
|
||||
----
|
||||
|
||||
[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
**2022/03/08: CAUTION, THIS TUTORIAL IS NO LONGER VALID on the `develop` branch after the `2022.w01` tag.**
|
||||
|
||||
**2022/03/08: CAUTION, THE LAST VALID TAG on `develop` branch is `2021.w51_c`.**
|
||||
|
||||
## Table of Contents ##
|
||||
|
||||
1. [Environment](#1-environment)
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
**2022/03/08: CAUTION, THIS TUTORIAL IS NO LONGER VALID on the `develop` branch after the `2022.w01` tag.**
|
||||
|
||||
**2022/03/08: CAUTION, THE LAST VALID TAG on `develop` branch is `2021.w51_c`.**
|
||||
|
||||
## Table of Contents ##
|
||||
|
||||
1. [Environment](#1-environment)
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ It is planned to enhance this simulator with the following functionalities:
|
||||
|
||||
This simulator connects a eNodeB and UEs through a nfapi interface, short-cutting the L1 layer. The objective of this simulator is to allow multi UEs simulation, with a large number of UEs (ideally up to 255 ) .Here to ease the platform setup, UEs are simulated via a single `lte-uesoftmodem` instance. Today the CI tests just with one UE and architecture has to be reviewed to allow a number of UE above about 16. This work is on-going.
|
||||
|
||||
As for the rf simulator, no specific hardware is required. The [L2 nfapi simlator page](L2NFAPI.md) contains the detailed documentation.
|
||||
As for the rf simulator, no specific hardware is required. The [L2 nfapi simulator page](L2NFAPI.md) contains the detailed documentation.
|
||||
|
||||
# L1 Simulator
|
||||
|
||||
|
||||
@@ -72,10 +72,10 @@ unsigned int crcbit (unsigned char * inputptr,
|
||||
unsigned int i, crc = 0, c;
|
||||
|
||||
while (octetlen-- > 0) {
|
||||
c = (*inputptr++) << 24;
|
||||
c = ((unsigned int)(*inputptr++)) << 24;
|
||||
|
||||
for (i = 8; i != 0; i--) {
|
||||
if ((1 << 31) & (c ^ crc))
|
||||
if ((1U << 31) & (c ^ crc))
|
||||
crc = (crc << 1) ^ poly;
|
||||
else
|
||||
crc <<= 1;
|
||||
|
||||
@@ -445,29 +445,10 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
}
|
||||
}
|
||||
|
||||
// PBCH
|
||||
pbch_vars[gNB_id]->rxdataF_ext = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
|
||||
pbch_vars[gNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) );
|
||||
pbch_vars[gNB_id]->llr = (int16_t *)malloc16_clear( 1920 ); //
|
||||
// RACH
|
||||
prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) );
|
||||
prach_vars[gNB_id]->prach = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) );
|
||||
|
||||
for (i=0; i<fp->nb_antennas_rx; i++) {
|
||||
pbch_vars[gNB_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 );
|
||||
|
||||
for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) {
|
||||
int idx = (j*fp->nb_antennas_rx)+i;
|
||||
pbch_vars[gNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates_time[idx]= (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) );
|
||||
pbch_vars[gNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 );
|
||||
}
|
||||
}
|
||||
|
||||
pbch_vars[gNB_id]->decoded_output = (uint8_t *)malloc16_clear(64);
|
||||
}
|
||||
|
||||
// initialization for the last instance of pdsch_vars (used for MU-MIMO)
|
||||
@@ -640,25 +621,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
free_and_zero(ue->srs_vars[gNB_id]);
|
||||
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++) {
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->rxdataF_ext[i]);
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
int idx = (j*fp->nb_antennas_rx)+i;
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->rxdataF_comp[idx]);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates[idx]);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates_time[idx]);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates_ext[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->rxdataF_ext);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->rxdataF_comp);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates_ext);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->dl_ch_estimates_time);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->llr);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]->decoded_output);
|
||||
free_and_zero(ue->pbch_vars[gNB_id]);
|
||||
|
||||
free_and_zero(ue->prach_vars[gNB_id]->prachF);
|
||||
|
||||
@@ -64,7 +64,7 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
|
||||
reset = 1;
|
||||
x2tmp0 = ((ue->frame_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17;
|
||||
x2 = (x2tmp0+(nid<<1))%(1<<31); //cinit
|
||||
x2 = (x2tmp0+(nid<<1))%(1U<<31); //cinit
|
||||
|
||||
for (n=0; n<NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD; n++) {
|
||||
ue->nr_gold_pdcch[0][ns][l][n] = lte_gold_generic(&x1, &x2, reset);
|
||||
@@ -95,7 +95,7 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
|
||||
|
||||
reset = 1;
|
||||
x2tmp0 = ((ue->frame_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17;
|
||||
x2 = (x2tmp0+(nid<<1)+nscid)%(1<<31); //cinit
|
||||
x2 = (x2tmp0+(nid<<1)+nscid)%(1U<<31); //cinit
|
||||
LOG_D(PHY,"UE DMRS slot %d, symb %d, x2 %x, nscid %d\n",ns,l,x2,nscid);
|
||||
|
||||
for (n=0; n<NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD; n++) {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
const int estimateSz, struct complex16 dl_ch_estimates_time[][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t subframe,
|
||||
unsigned char clear,
|
||||
@@ -60,8 +61,8 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
int j = (i < 0) ? (i + frame_parms->ofdm_symbol_size) : i;
|
||||
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
|
||||
int Re = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[(j<<1)];
|
||||
int Im = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[1+(j<<1)];
|
||||
int Re = dl_ch_estimates_time[aa][j].r;
|
||||
int Im = dl_ch_estimates_time[aa][j].i;
|
||||
temp += (Re*Re/2) + (Im*Im/2);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
|
||||
#include "filt16a_32.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
|
||||
//#define DEBUG_PDSCH
|
||||
//#define DEBUG_PDCCH
|
||||
@@ -43,7 +44,6 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_SSB *current_ssb)
|
||||
{
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
unsigned char aarx;
|
||||
unsigned short k;
|
||||
unsigned int pilot_cnt;
|
||||
int16_t ch[2],*pil,*rxF;
|
||||
@@ -77,7 +77,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
|
||||
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
@@ -197,6 +197,9 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
@@ -206,16 +209,14 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
uint8_t n_hf)
|
||||
{
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
unsigned char aarx,p;
|
||||
unsigned short k;
|
||||
unsigned int pilot_cnt;
|
||||
int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr;
|
||||
int16_t *pil,*rxF,*dl_ch,*fl,*fm,*fr;
|
||||
int ch_offset,symbol_offset;
|
||||
//int slot_pbch;
|
||||
|
||||
uint8_t nushift;
|
||||
int **dl_ch_estimates =ue->pbch_vars[gNB_id]->dl_ch_estimates;
|
||||
int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF;
|
||||
int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF;
|
||||
|
||||
nushift = ue->frame_parms.Nid_cell%4;
|
||||
ue->frame_parms.nushift = nushift;
|
||||
@@ -269,17 +270,57 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
break;
|
||||
}
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
idftsizeidx = IDFT_256;
|
||||
break;
|
||||
|
||||
case 512:
|
||||
idftsizeidx = IDFT_512;
|
||||
break;
|
||||
|
||||
case 1024:
|
||||
idftsizeidx = IDFT_1024;
|
||||
break;
|
||||
|
||||
case 1536:
|
||||
idftsizeidx = IDFT_1536;
|
||||
break;
|
||||
|
||||
case 2048:
|
||||
idftsizeidx = IDFT_2048;
|
||||
break;
|
||||
|
||||
case 3072:
|
||||
idftsizeidx = IDFT_3072;
|
||||
break;
|
||||
|
||||
case 4096:
|
||||
idftsizeidx = IDFT_4096;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unsupported ofdm symbol size \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
|
||||
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
|
||||
|
||||
memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size));
|
||||
memset(dl_ch,0,sizeof(*dl_ch)*(ue->frame_parms.ofdm_symbol_size));
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
|
||||
@@ -289,6 +330,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
// Treat first 2 pilots specially (left edge)
|
||||
int16_t ch[2];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
@@ -402,62 +444,18 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
}
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
idftsizeidx = IDFT_256;
|
||||
break;
|
||||
|
||||
case 512:
|
||||
idftsizeidx = IDFT_512;
|
||||
break;
|
||||
|
||||
case 1024:
|
||||
idftsizeidx = IDFT_1024;
|
||||
break;
|
||||
|
||||
case 1536:
|
||||
idftsizeidx = IDFT_1536;
|
||||
break;
|
||||
|
||||
case 2048:
|
||||
idftsizeidx = IDFT_2048;
|
||||
break;
|
||||
|
||||
case 3072:
|
||||
idftsizeidx = IDFT_3072;
|
||||
break;
|
||||
|
||||
case 4096:
|
||||
idftsizeidx = IDFT_4096;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unsupported ofdm symbol size \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if( dmrss == 2) // update time statistics for last PBCH symbol
|
||||
{
|
||||
// do ifft of channel estimate
|
||||
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++)
|
||||
for (p=0; p<ue->frame_parms.nb_antenna_ports_gNB; p++) {
|
||||
if (ue->pbch_vars[gNB_id]->dl_ch_estimates[(p*ue->frame_parms.nb_antennas_rx)+aarx])
|
||||
{
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, proc->thread_id, symbol, ch_offset);
|
||||
idft(idftsizeidx,
|
||||
(int16_t*) &ue->pbch_vars[gNB_id]->dl_ch_estimates[(p*ue->frame_parms.nb_antennas_rx)+aarx][ch_offset],
|
||||
(int16_t*) ue->pbch_vars[gNB_id]->dl_ch_estimates_time[(p*ue->frame_parms.nb_antennas_rx)+aarx],1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
|
||||
idft(idftsizeidx,
|
||||
(int16_t*) &dl_ch_estimates[aarx][ch_offset],
|
||||
(int16_t*) dl_ch_estimates_time[aarx],
|
||||
1);
|
||||
}
|
||||
}
|
||||
if (dmrss == 2)
|
||||
UEscopeCopy(ue, pbchDlChEstimateTime, (void*)dl_ch_estimates_time, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, idftsizeidx);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,10 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_SSB *current_ssb);
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
@@ -79,6 +82,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t subframe,
|
||||
unsigned char clear,
|
||||
|
||||
@@ -146,17 +146,23 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
|
||||
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
// computing channel estimation for selected best ssb
|
||||
const int estimateSz=7*2*frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][estimateSz];
|
||||
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
|
||||
nr_pbch_channel_estimation(ue,proc,0,0,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf);
|
||||
nr_pbch_channel_estimation(ue,estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc,0,0,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf);
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
|
||||
fapiPbch_t result;
|
||||
ret = nr_rx_pbch(ue,
|
||||
proc,
|
||||
ue->pbch_vars[0],
|
||||
estimateSz, dl_ch_estimates,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
temp_ptr->i_ssb,
|
||||
SISO);
|
||||
SISO,
|
||||
&result);
|
||||
|
||||
temp_ptr=temp_ptr->next_ssb;
|
||||
}
|
||||
|
||||
@@ -36,28 +36,30 @@
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
#include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h>
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
|
||||
//#define DEBUG_PBCH
|
||||
//#define DEBUG_PBCH
|
||||
//#define DEBUG_PBCH_ENCODING
|
||||
|
||||
//#include "PHY_INTERFACE/defs.h"
|
||||
//#include "PHY_INTERFACE/defs.h"
|
||||
|
||||
#define PBCH_A 24
|
||||
|
||||
#define PBCH_MAX_RE_PER_SYMBOL (20*12)
|
||||
#define PBCH_MAX_RE (PBCH_MAX_RE_PER_SYMBOL*4)
|
||||
#define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7])
|
||||
|
||||
uint16_t nr_pbch_extract(int **rxdataF,
|
||||
int **dl_ch_estimates,
|
||||
int **rxdataF_ext,
|
||||
int **dl_ch_estimates_ext,
|
||||
uint32_t symbol,
|
||||
uint32_t s_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
static uint16_t nr_pbch_extract(int **rxdataF,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
uint32_t symbol,
|
||||
uint32_t s_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
uint16_t rb;
|
||||
uint8_t i,j,aarx;
|
||||
int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
|
||||
int nushiftmod4 = frame_parms->nushift;
|
||||
|
||||
AssertFatal(symbol>=1 && symbol<5,
|
||||
"symbol %d illegal for PBCH extraction\n",
|
||||
symbol);
|
||||
@@ -65,9 +67,8 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);
|
||||
|
||||
rxF = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
|
||||
rxF_ext = &rxdataF_ext[aarx][symbol*20*12];
|
||||
struct complex16 *rxF = (struct complex16 *)&rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
|
||||
struct complex16 *rxF_ext = rxdataF_ext[aarx];
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",frame_parms->nushift,
|
||||
(rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol);
|
||||
@@ -76,7 +77,6 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
for (int i =0; i<8; i++) {
|
||||
printf("rxF [%d]= %d\n",i,rxF[i]);
|
||||
printf("pbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]);
|
||||
printf("rxF ext addr %p\n", &rxF_ext[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -91,19 +91,18 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
(i!=(nushiftmod4+8))) {
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(9*rb) + j,
|
||||
((int16_t *)&rxF_ext[j])[0],
|
||||
((int16_t *)&rxF_ext[j])[1],
|
||||
printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",
|
||||
(9*rb) + j,
|
||||
rxF_ext[j].r, rxF_ext[j].i,
|
||||
rx_offset,
|
||||
((int16_t *)&rxF[rx_offset])[0],
|
||||
((int16_t *)&rxF[rx_offset])[1]);
|
||||
rxF[rx_offset].r,rxF[rx_offset].j;
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
|
||||
rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size);
|
||||
//rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1);
|
||||
}
|
||||
}
|
||||
|
||||
rxF_ext+=9;
|
||||
} else { //symbol 2
|
||||
@@ -115,11 +114,9 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(rb<4) ? (9*rb) + j : (9*(rb-12))+j,
|
||||
((int16_t *)&rxF_ext[j])[0],
|
||||
((int16_t *)&rxF_ext[j])[1],
|
||||
rxF_ext[j].r, rxF_ext[j].i,
|
||||
rx_offset,
|
||||
((int16_t *)&rxF[rx_offset])[0],
|
||||
((int16_t *)&rxF[rx_offset])[1]);
|
||||
rxF[rx_offset].r,rxF[rx_offset].j;
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
@@ -129,16 +126,16 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
}
|
||||
|
||||
rxF_ext+=9;
|
||||
} else{ //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12);
|
||||
rx_offset = (rx_offset+12)%(frame_parms->ofdm_symbol_size);
|
||||
}
|
||||
} else { //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12);
|
||||
rx_offset = (rx_offset+12)%(frame_parms->ofdm_symbol_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
|
||||
struct complex16 *dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
|
||||
|
||||
//printf("dl_ch0 addr %p\n",dl_ch0);
|
||||
dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*20*12];
|
||||
struct complex16 *dl_ch0_ext = dl_ch_estimates_ext[aarx];
|
||||
|
||||
for (rb=0; rb<20; rb++) {
|
||||
j=0;
|
||||
@@ -150,15 +147,11 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
(i!=(nushiftmod4+8))) {
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
#ifdef DEBUG_PBCH
|
||||
|
||||
if ((rb==0) && (i<2))
|
||||
printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j,
|
||||
((int16_t *)&dl_ch0_ext[j])[0],
|
||||
((int16_t *)&dl_ch0_ext[j])[1],
|
||||
dl_ch0_ext[j].r, dl_ch0_ext[j].i,
|
||||
i,
|
||||
((int16_t *)&dl_ch0[i])[0],
|
||||
((int16_t *)&dl_ch0[i])[1]);
|
||||
|
||||
dl_ch0[j].r, dl_ch0[j].i,
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
@@ -175,11 +168,9 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j,
|
||||
((int16_t *)&dl_ch0_ext[j])[0],
|
||||
((int16_t *)&dl_ch0_ext[j])[1],
|
||||
dl_ch0_ext[j].r, dl_ch0_ext[j].i,
|
||||
i,
|
||||
((int16_t *)&dl_ch0[i])[0],
|
||||
((int16_t *)&dl_ch0[i])[1]);
|
||||
dl_ch0[j].r, dl_ch0[j].i,
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
@@ -199,11 +190,10 @@ uint16_t nr_pbch_extract(int **rxdataF,
|
||||
//__m128i avg128;
|
||||
|
||||
//compute average channel_level on each (TX,RX) antenna pair
|
||||
int nr_pbch_channel_level(int **dl_ch_estimates_ext,
|
||||
int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint32_t symbol) {
|
||||
int16_t rb, nb_rb=20;
|
||||
uint8_t aarx;
|
||||
int nb_re) {
|
||||
int16_t nb_rb=nb_re/12;
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
__m128i avg128;
|
||||
__m128i *dl_ch128;
|
||||
@@ -213,22 +203,23 @@ int nr_pbch_channel_level(int **dl_ch_estimates_ext,
|
||||
#endif
|
||||
int avg1=0,avg2=0;
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
//clear average level
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_setzero_si128();
|
||||
dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*20*12];
|
||||
dl_ch128=(__m128i *)dl_ch_estimates_ext[aarx];
|
||||
#elif defined(__arm__)
|
||||
avg128 = vdupq_n_s32(0);
|
||||
dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][symbol*20*12];
|
||||
dl_ch128=(int16x8_t *)dl_ch_estimates_ext[aarx];
|
||||
#endif
|
||||
|
||||
for (rb=0; rb<nb_rb; rb++) {
|
||||
for (int rb=0; rb<nb_rb; rb++) {
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
|
||||
#elif defined(__arm__)
|
||||
abort();
|
||||
// to be filled in
|
||||
#endif
|
||||
dl_ch128+=3;
|
||||
@@ -251,35 +242,19 @@ int nr_pbch_channel_level(int **dl_ch_estimates_ext,
|
||||
//LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
_mm_empty();
|
||||
_m_empty();
|
||||
#endif
|
||||
return(avg2);
|
||||
}
|
||||
|
||||
void nr_pbch_channel_compensation(int **rxdataF_ext,
|
||||
int **dl_ch_estimates_ext,
|
||||
int **rxdataF_comp,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint32_t symbol,
|
||||
uint8_t output_shift) {
|
||||
const uint16_t nb_re=symbol == 2 ? 72 : 180;
|
||||
AssertFatal((symbol > 0 && symbol < 4),
|
||||
"symbol %d is illegal for PBCH DM-RS\n",
|
||||
symbol);
|
||||
|
||||
// printf("comp: symbol %d : nb_re %d\n",symbol,nb_re);
|
||||
|
||||
static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t output_shift) {
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
vect128 *dl_ch128 = (vect128 *)&dl_ch_estimates_ext[aarx][symbol*20*12];
|
||||
vect128 *rxdataF128 = (vect128 *)&rxdataF_ext[aarx][symbol*20*12];
|
||||
vect128 *rxdataF_comp128 = (vect128 *)&rxdataF_comp[aarx][symbol*20*12];
|
||||
/*
|
||||
printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[aarx][symbol*20*12]);
|
||||
printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol);
|
||||
printf("rxdataf_comp addr %p\n",&rxdataF_comp[aarx][symbol*20*12]);
|
||||
*/
|
||||
vect128 *dl_ch128 = (vect128 *)dl_ch_estimates_ext[aarx];
|
||||
vect128 *rxdataF128 = (vect128 *)rxdataF_ext[aarx];
|
||||
vect128 *rxdataF_comp128 = (vect128 *)rxdataF_comp[aarx];
|
||||
|
||||
for (int re=0; re<nb_re; re+=12) {
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
@@ -327,16 +302,18 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
|
||||
}
|
||||
|
||||
static void nr_pbch_unscrambling(NR_UE_PBCH *pbch,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask) {
|
||||
int16_t *demod_pbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask,
|
||||
uint32_t pbch_a_prime,
|
||||
uint32_t *pbch_a_interleaved) {
|
||||
uint8_t reset, offset;
|
||||
uint32_t x1, x2, s=0;
|
||||
uint8_t k=0;
|
||||
int16_t *demod_pbch_e = pbch->llr;
|
||||
reset = 1;
|
||||
// x1 is set in first call to lte_gold_generic
|
||||
x2 = Nid; //this is c_init
|
||||
@@ -361,10 +338,10 @@ static void nr_pbch_unscrambling(NR_UE_PBCH *pbch,
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
(pbch->pbch_a_interleaved) ^= ((unscrambling_mask>>i)&1)? ((pbch->pbch_a_prime>>i)&1)<<i : (((pbch->pbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<<i;
|
||||
*pbch_a_interleaved ^= ((unscrambling_mask>>i)&1)? ((pbch_a_prime>>i)&1)<<i : (((pbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<<i;
|
||||
k += (!((unscrambling_mask>>i)&1));
|
||||
#ifdef DEBUG_PBCH_ENCODING
|
||||
printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, pbch->pbch_a_interleaved,
|
||||
printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, *pbch_a_interleaved,
|
||||
(!((unscrambling_mask>>i)&1)));
|
||||
#endif
|
||||
} else {
|
||||
@@ -386,18 +363,16 @@ static void nr_pbch_unscrambling(NR_UE_PBCH *pbch,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len) {
|
||||
uint16_t i;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
static void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len) {
|
||||
for (int i=0; i<len; i++) {
|
||||
if (pbch_llr[i]>31)
|
||||
pbch_llr8[i]=32;
|
||||
else if (pbch_llr[i]<-31)
|
||||
pbch_llr8[i]=-32;
|
||||
else
|
||||
pbch_llr8[i] = (char)(pbch_llr[i]);
|
||||
pbch_llr8[i]=pbch_llr[i];
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -410,36 +385,33 @@ uint8_t pbch_deinterleaving_pattern[32] = {28,0,31,30,7,29,25,27,5,8,24,9,10,11,
|
||||
|
||||
int nr_rx_pbch( PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz, struct complex16 dl_ch_estimates [][estimateSz],
|
||||
NR_UE_PBCH *nr_ue_pbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t gNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode) {
|
||||
|
||||
MIMO_mode_t mimo_mode,
|
||||
fapiPbch_t *result) {
|
||||
NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
|
||||
int max_h=0;
|
||||
int symbol;
|
||||
//uint8_t pbch_a[64];
|
||||
//FT ?? cppcheck doesn't like pbch_a allocation because of line 525..and i don't get what this variable is for..
|
||||
//uint8_t *pbch_a = malloc(sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
|
||||
//uint32_t pbch_a_prime;
|
||||
int16_t *pbch_e_rx;
|
||||
uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output;
|
||||
//FT ?? cppcheck doesn't like pbch_a allocation because of line 525..and i don't get what this variable is for..
|
||||
//uint8_t *pbch_a = malloc(sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
|
||||
uint8_t nushift;
|
||||
uint16_t M;
|
||||
uint8_t Lmax=frame_parms->Lmax;
|
||||
uint8_t Lmax=frame_parms->Lmax;
|
||||
//uint16_t crc;
|
||||
//unsigned short idx_demod =0;
|
||||
uint32_t decoderState=0;
|
||||
//uint8_t decoderListSize = 8, pathMetricAppr = 0;
|
||||
//time_stats_t polar_decoder_init,polar_rate_matching,decoding,bit_extraction,deinterleaving;
|
||||
//time_stats_t path_metric,sorting,update_LLR;
|
||||
// FT ?? cppcheck fix memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
|
||||
// FT ?? cppcheck fix memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
|
||||
//printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell);
|
||||
|
||||
pbch_e_rx = &nr_ue_pbch_vars->llr[0];
|
||||
// clear LLR buffer
|
||||
memset(nr_ue_pbch_vars->llr,0,NR_POLAR_PBCH_E);
|
||||
int16_t pbch_e_rx[960]= {0}; //Fixme: previous version erase only NR_POLAR_PBCH_E bytes
|
||||
int16_t pbch_unClipped[960]= {0};
|
||||
int pbch_e_rx_idx=0;
|
||||
int symbol_offset=1;
|
||||
|
||||
if (ue->is_synchronized > 0)
|
||||
@@ -447,20 +419,24 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
|
||||
else
|
||||
symbol_offset=0;
|
||||
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
//printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF);
|
||||
write_output("rxdataF0_pbch.m","rxF0pbch",
|
||||
&nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1);
|
||||
#endif
|
||||
|
||||
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
||||
for (symbol=1; symbol<4; symbol++) {
|
||||
double log2_maxh;
|
||||
|
||||
for (symbol=1; symbol<4; symbol++) {
|
||||
const uint16_t nb_re=symbol == 2 ? 72 : 180;
|
||||
struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
|
||||
struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
|
||||
memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
||||
nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF,
|
||||
nr_ue_pbch_vars->dl_ch_estimates,
|
||||
nr_ue_pbch_vars->rxdataF_ext,
|
||||
nr_ue_pbch_vars->dl_ch_estimates_ext,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
symbol,
|
||||
symbol_offset,
|
||||
frame_parms);
|
||||
@@ -470,142 +446,139 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
if (symbol == 1) {
|
||||
max_h = nr_pbch_channel_level(nr_ue_pbch_vars->dl_ch_estimates_ext,
|
||||
max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
|
||||
frame_parms,
|
||||
symbol);
|
||||
nr_ue_pbch_vars->log2_maxh = 3+(log2_approx(max_h)/2);
|
||||
nb_re);
|
||||
log2_maxh = 3+(log2_approx(max_h)/2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n",nr_ue_pbch_vars->log2_maxh,max_h);
|
||||
#endif
|
||||
nr_pbch_channel_compensation(nr_ue_pbch_vars->rxdataF_ext,
|
||||
nr_ue_pbch_vars->dl_ch_estimates_ext,
|
||||
nr_ue_pbch_vars->rxdataF_comp,
|
||||
struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
|
||||
nr_pbch_channel_compensation(rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
nb_re,
|
||||
rxdataF_comp,
|
||||
frame_parms,
|
||||
symbol,
|
||||
nr_ue_pbch_vars->log2_maxh); // log2_maxh+I0_shift
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
/*if (frame_parms->nb_antennas_rx > 1)
|
||||
pbch_detection_mrc(frame_parms,
|
||||
nr_ue_pbch_vars->rxdataF_comp,
|
||||
rxdataF_comp,
|
||||
symbol);*/
|
||||
|
||||
/*
|
||||
if (mimo_mode == ALAMOUTI) {
|
||||
nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol);
|
||||
nr_pbch_alamouti(frame_parms,rxdataF_comp,symbol);
|
||||
} else if (mimo_mode != SISO) {
|
||||
LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n");
|
||||
return(-1);
|
||||
}
|
||||
*/
|
||||
if (symbol==2) {
|
||||
nr_pbch_quantize(pbch_e_rx,
|
||||
(short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
|
||||
144);
|
||||
pbch_e_rx+=144;
|
||||
} else {
|
||||
nr_pbch_quantize(pbch_e_rx,
|
||||
(short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
|
||||
360);
|
||||
pbch_e_rx+=360;
|
||||
}
|
||||
int nb=symbol==2 ? 144 : 360;
|
||||
nr_pbch_quantize(pbch_e_rx+pbch_e_rx_idx,
|
||||
(short *)rxdataF_comp[0],
|
||||
nb);
|
||||
memcpy(pbch_unClipped+pbch_e_rx_idx, rxdataF_comp[0], nb*sizeof(int16_t));
|
||||
pbch_e_rx_idx+=nb;
|
||||
}
|
||||
|
||||
// legacy code use int16, but it is complex16
|
||||
UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx/2);
|
||||
UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx);
|
||||
#ifdef DEBUG_PBCH
|
||||
write_output("rxdataF_comp.m","rxFcomp",&nr_ue_pbch_vars->rxdataF_comp[0][240],240*3,1,1);
|
||||
#endif
|
||||
pbch_e_rx = nr_ue_pbch_vars->llr;
|
||||
//demod_pbch_e = nr_ue_pbch_vars->demod_pbch_e;
|
||||
// FT?? cppcheck fix - pbch_a = nr_ue_pbch_vars->pbch_a;
|
||||
#ifdef DEBUG_PBCH
|
||||
//pbch_e_rx = &nr_ue_pbch_vars->llr[0];
|
||||
short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][20*12]);
|
||||
|
||||
write_output("rxdataF_comp.m","rxFcomp",rxdataF_comp[0],240*3,1,1);
|
||||
short *p = (short *)rxdataF_comp[0]);
|
||||
|
||||
for (int cnt = 0; cnt < 864 ; cnt++)
|
||||
printf("pbch rx llr %d\n",*(pbch_e_rx+cnt));
|
||||
|
||||
|
||||
#endif
|
||||
//un-scrambling
|
||||
M = NR_POLAR_PBCH_E;
|
||||
nushift = (Lmax==4)? i_ssb&3 : i_ssb&7;
|
||||
uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041;
|
||||
|
||||
nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0,0);
|
||||
uint32_t pbch_a_interleaved=0;
|
||||
uint32_t pbch_a_prime=0;
|
||||
nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E,
|
||||
0, 0, pbch_a_prime, &pbch_a_interleaved);
|
||||
//polar decoding de-rate matching
|
||||
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&nr_ue_pbch_vars->pbch_a_prime,0,
|
||||
uint64_t tmp=0;
|
||||
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
pbch_a_prime=tmp;
|
||||
if(decoderState)
|
||||
return(decoderState);
|
||||
|
||||
if(decoderState) return(decoderState);
|
||||
|
||||
// printf("polar decoder output 0x%08x\n",nr_ue_pbch_vars->pbch_a_prime);
|
||||
// printf("polar decoder output 0x%08x\n",pbch_a_prime);
|
||||
// Decoder reversal
|
||||
uint32_t a_reversed=0;
|
||||
|
||||
for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)nr_ue_pbch_vars->pbch_a_prime>>i)&1)<<(31-i);
|
||||
a_reversed |= (((uint64_t)pbch_a_prime>>i)&1)<<(31-i);
|
||||
|
||||
nr_ue_pbch_vars->pbch_a_prime = a_reversed;
|
||||
pbch_a_prime = a_reversed;
|
||||
//payload un-scrambling
|
||||
nr_ue_pbch_vars->pbch_a_interleaved=0;
|
||||
M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
|
||||
nushift = ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>6)&1)<<1);
|
||||
nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1,unscrambling_mask);
|
||||
//printf("nushift %d sfn 3rd %d 2nd %d", nushift,((nr_ue_pbch_vars->pbch_a_prime>>6)&1), ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) );
|
||||
nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1);
|
||||
pbch_a_interleaved=0;
|
||||
nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
1, unscrambling_mask, pbch_a_prime, &pbch_a_interleaved);
|
||||
//printf("nushift %d sfn 3rd %d 2nd %d", nushift,((pbch_a_prime>>6)&1), ((pbch_a_prime>>24)&1) );
|
||||
//payload deinterleaving
|
||||
//uint32_t in=0;
|
||||
uint32_t out=0;
|
||||
|
||||
for (int i=0; i<32; i++) {
|
||||
out |= ((nr_ue_pbch_vars->pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]);
|
||||
out |= ((pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]);
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("i %d in 0x%08x out 0x%08x ilv %d (in>>i)&1) 0x%08x\n", i, nr_ue_pbch_vars->pbch_a_interleaved, out, pbch_deinterleaving_pattern[i], (nr_ue_pbch_vars->pbch_a_interleaved>>i)&1);
|
||||
printf("i %d in 0x%08x out 0x%08x ilv %d (in>>i)&1) 0x%08x\n", i, pbch_a_interleaved, out, pbch_deinterleaving_pattern[i], (pbch_a_interleaved>>i)&1);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t payload = 0;
|
||||
//uint8_t xtra_byte = 0;
|
||||
nr_ue_pbch_vars->xtra_byte = (out>>24)&0xff;
|
||||
result->xtra_byte = (out>>24)&0xff;
|
||||
|
||||
for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
|
||||
payload |= ((out>>i)&1)<<(NR_POLAR_PBCH_PAYLOAD_BITS-i-1);
|
||||
|
||||
|
||||
for (int i=0; i<3; i++)
|
||||
decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff);
|
||||
|
||||
frame_parms->half_frame_bit = ((nr_ue_pbch_vars->xtra_byte>>4)&0x01); // computing the half frame index from the extra byte
|
||||
|
||||
result->decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff);
|
||||
|
||||
frame_parms->half_frame_bit = (result->xtra_byte>>4)&0x01; // computing the half frame index from the extra byte
|
||||
frame_parms->ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8
|
||||
|
||||
if (Lmax == 64) { // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte
|
||||
for (int i=0; i<3; i++)
|
||||
frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i));
|
||||
frame_parms->ssb_index += (((result->xtra_byte>>(7-i))&0x01)<<(3+i));
|
||||
}
|
||||
|
||||
ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index);
|
||||
|
||||
if (frame_parms->half_frame_bit)
|
||||
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
||||
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
||||
|
||||
uint8_t frame_number_4lsb = 0;
|
||||
|
||||
for (int i=0; i<4; i++)
|
||||
frame_number_4lsb |= ((nr_ue_pbch_vars->xtra_byte>>i)&1)<<(3-i);
|
||||
|
||||
frame_number_4lsb |= ((result->xtra_byte>>i)&1)<<(3-i);
|
||||
|
||||
proc->decoded_frame_rx = frame_number_4lsb;
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("xtra_byte %x payload %x\n", nr_ue_pbch_vars->xtra_byte, payload);
|
||||
printf("xtra_byte %x payload %x\n", xtra_byte, payload);
|
||||
|
||||
for (int i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++) {
|
||||
// printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]);
|
||||
printf("[PBCH] decoder payload[%d] = %x\n",i,decoded_output[i]);
|
||||
printf("[PBCH] decoder payload[%d] = %x\n",i,result->decoded_output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t *rx_ind=calloc(sizeof(*rx_ind),1);
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus, proc);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus, proc,(void *)result);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication, NULL);
|
||||
|
||||
@@ -1152,11 +1152,14 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin
|
||||
*/
|
||||
int nr_rx_pbch( PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_UE_PBCH *nr_ue_pbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t eNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode);
|
||||
MIMO_mode_t mimo_mode,
|
||||
fapiPbch_t* result);
|
||||
|
||||
int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
|
||||
@@ -861,7 +861,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||
|
||||
/* perform correlation of rx data and pss sequence ie it is a dot product */
|
||||
result = dot_product64((short*)primary_synchro_time_nr[pss_index],
|
||||
(short*) &(rxdata[ar][n+is*frame_parms->samples_per_frame]),
|
||||
(short*)&(rxdata[ar][n+is*frame_parms->samples_per_frame]),
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
pss_corr_ue[pss_index][n] += abs64(result);
|
||||
|
||||
@@ -40,6 +40,13 @@ const FL_COLOR water_colors[4] = {FL_BLUE,FL_GREEN,FL_YELLOW,FL_RED};
|
||||
typedef struct complex16 scopeSample_t;
|
||||
#define SquaredNorm(VaR) ((VaR).r*(VaR).r+(VaR).i*(VaR).i)
|
||||
|
||||
typedef struct {
|
||||
int dataSize;
|
||||
int elementSz;
|
||||
int colSz;
|
||||
int lineSz;
|
||||
} scopeGraphData_t;
|
||||
|
||||
typedef struct OAIgraph {
|
||||
FL_OBJECT *graph;
|
||||
FL_OBJECT *text;
|
||||
@@ -56,7 +63,7 @@ typedef struct OAIgraph {
|
||||
boolean_t initDone;
|
||||
int iteration;
|
||||
void (*gNBfunct) (struct OAIgraph *graph, scopeData_t *p, int UE_id);
|
||||
void (*nrUEfunct)(struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id);
|
||||
void (*nrUEfunct)(scopeGraphData_t **data, struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id);
|
||||
} OAIgraph_t;
|
||||
|
||||
/* Forms and Objects */
|
||||
@@ -140,7 +147,7 @@ static OAIgraph_t gNBcommonGraph( void (*funct) (OAIgraph_t *graph, scopeData_t
|
||||
return graph;
|
||||
}
|
||||
|
||||
static OAIgraph_t nrUEcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id),
|
||||
static OAIgraph_t nrUEcommonGraph( void (*funct) (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id),
|
||||
int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
|
||||
OAIgraph_t graph;
|
||||
commonGraph(&graph, type, x, y, w, h, label, pointColor);
|
||||
@@ -341,7 +348,7 @@ static void timeResponse (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
|
||||
static void gNBfreqWaterFall (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
|
||||
NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms;
|
||||
//use 1st antenna
|
||||
genericWaterFall(graph, (scopeSample_t *)p->rxdataF, frame_parms->samples_per_frame_wCP,
|
||||
genericWaterFall(graph, (scopeSample_t *)p->liveData, frame_parms->samples_per_frame_wCP,
|
||||
frame_parms->slots_per_frame,
|
||||
"X axis: Frequency domain, one subframe");
|
||||
}
|
||||
@@ -515,6 +522,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
|
||||
|
||||
//fl_check_forms();
|
||||
}
|
||||
|
||||
static void *scope_thread_gNB(void *arg) {
|
||||
scopeData_t *p=(scopeData_t *) arg;
|
||||
size_t stksize=0;
|
||||
@@ -539,11 +547,12 @@ static void *scope_thread_gNB(void *arg) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void copyRxdataF(int32_t *data, int slot, void *scopeData) {
|
||||
scopeData_t *scope=(scopeData_t *)scopeData;
|
||||
memcpy(scope->rxdataF + slot*scope->gNB->frame_parms.samples_per_slot_wCP,
|
||||
memcpy(((int32_t *)scope->liveData) + slot*scope->gNB->frame_parms.samples_per_slot_wCP,
|
||||
data,
|
||||
scope->gNB->frame_parms.samples_per_slot_wCP);
|
||||
scope->gNB->frame_parms.samples_per_slot_wCP*sizeof(int32_t));
|
||||
}
|
||||
|
||||
void gNBinitScope(scopeParms_t *p) {
|
||||
@@ -554,11 +563,11 @@ void gNBinitScope(scopeParms_t *p) {
|
||||
scope->ru=p->ru;
|
||||
scope->gNB=p->gNB;
|
||||
scope->slotFunc=copyRxdataF;
|
||||
AssertFatal(scope->rxdataF=(int32_t *) calloc(p->gNB->frame_parms.samples_per_frame_wCP*sizeof(int32_t),1),"");
|
||||
AssertFatal(scope->liveData= calloc(p->gNB->frame_parms.samples_per_frame_wCP*sizeof(int32_t),1),"");
|
||||
pthread_t forms_thread;
|
||||
threadCreate(&forms_thread, scope_thread_gNB, p->gNB->scopeData, "scope", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void ueWaterFall (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// Received signal in time domain of receive antenna 0
|
||||
genericWaterFall(graph,
|
||||
(scopeSample_t *) phy_vars_ue->common_vars.rxdata[0],
|
||||
@@ -574,13 +583,19 @@ static void ueTimeResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int
|
||||
phy_vars_ue->frame_parms.samples_per_frame);
|
||||
}
|
||||
*/
|
||||
static void ueChannelResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
static void ueChannelResponse (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// Channel Impulse Response
|
||||
genericPowerPerAntena(graph, phy_vars_ue->frame_parms.nb_antennas_rx,
|
||||
(const scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates_time,
|
||||
phy_vars_ue->frame_parms.ofdm_symbol_size>>3);
|
||||
if (!data[pbchDlChEstimateTime])
|
||||
return;
|
||||
|
||||
const scopeSample_t *tmp=(scopeSample_t *)(data[pbchDlChEstimateTime]+1);
|
||||
genericPowerPerAntena(graph, data[pbchDlChEstimateTime]->colSz,
|
||||
&tmp,
|
||||
data[pbchDlChEstimateTime]->lineSz);
|
||||
}
|
||||
static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
|
||||
|
||||
static void ueFreqWaterFall (scopeGraphData_t **data, OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
|
||||
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->frame_parms;
|
||||
//use 1st antenna
|
||||
genericWaterFall(graph,
|
||||
@@ -624,56 +639,44 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue
|
||||
oai_xygraph(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,0,10);
|
||||
}
|
||||
*/
|
||||
static void uePbchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void uePbchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PBCH LLRs
|
||||
if ( !phy_vars_ue->pbch_vars[eNB_id]->llr)
|
||||
if ( !data[pbchLlr])
|
||||
return;
|
||||
|
||||
int16_t *pbch_llr = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->llr;
|
||||
const int sz=data[pbchLlr]->lineSz;
|
||||
//const int antennas=data[pbchLlr]->colSz;
|
||||
// We take the first antenna only for now
|
||||
int16_t *llrs = (int16_t *) (data[pbchLlr]+1);
|
||||
float *llr_pbch, *bit_pbch;
|
||||
oai_xygraph_getbuff(graph, &bit_pbch, &llr_pbch, 864, 0);
|
||||
oai_xygraph_getbuff(graph, &bit_pbch, &llr_pbch, sz, 0);
|
||||
|
||||
for (int i=0; i<864; i++) {
|
||||
llr_pbch[i] = (float) pbch_llr[i];
|
||||
for (int i=0; i<sz; i++) {
|
||||
llr_pbch[i] = llrs[i];
|
||||
}
|
||||
|
||||
oai_xygraph(graph,bit_pbch,llr_pbch,864,0,10);
|
||||
oai_xygraph(graph,bit_pbch,llr_pbch,sz,0,10);
|
||||
}
|
||||
static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
static void uePbchIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PBCH I/Q of MF Output
|
||||
if (!phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0])
|
||||
if (!data[pbchRxdataF_comp])
|
||||
return;
|
||||
|
||||
scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
|
||||
scopeSample_t *pbch_comp = (scopeSample_t *) (data[pbchRxdataF_comp]+1);
|
||||
const int sz=data[pbchRxdataF_comp]->lineSz;
|
||||
float *I, *Q;
|
||||
oai_xygraph_getbuff(graph, &I, &Q, 180*3, 0);
|
||||
memset(I,0,180*3*sizeof(*I));
|
||||
memset(Q,0,180*3*sizeof(*Q));
|
||||
int first_symbol=1;
|
||||
int base=0;
|
||||
oai_xygraph_getbuff(graph, &I, &Q, sz, 0);
|
||||
|
||||
for (int symbol=first_symbol; symbol<(first_symbol+3); symbol++) {
|
||||
int nb_re;
|
||||
|
||||
if (symbol == 2 || symbol == 6)
|
||||
nb_re = 72;
|
||||
else
|
||||
nb_re = 180;
|
||||
|
||||
AssertFatal(base+nb_re<180*3,"");
|
||||
|
||||
for (int i=0; i<nb_re; i++) {
|
||||
I[base+i] = pbch_comp[symbol*20*12+i].r;
|
||||
Q[base+i] = pbch_comp[symbol*20*12+i].i;
|
||||
}
|
||||
|
||||
base+=nb_re;
|
||||
for (int i=0; i<sz; i++) {
|
||||
I[i]=pbch_comp[i].r;
|
||||
Q[i]=pbch_comp[i].i;
|
||||
}
|
||||
|
||||
AssertFatal(base <= 180*3,"");
|
||||
oai_xygraph(graph,I,Q,base,0, 10);
|
||||
oai_xygraph(graph, I, Q, sz, 0, true);
|
||||
}
|
||||
static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
static void uePcchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PDCCH LLRs
|
||||
if (!phy_vars_ue->pdcch_vars[0][eNB_id]->llr)
|
||||
return;
|
||||
@@ -698,7 +701,7 @@ static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
||||
AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, "");
|
||||
oai_xygraph(graph,bit,llr,base,0,10);
|
||||
}
|
||||
static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void uePcchIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PDCCH I/Q of MF Output
|
||||
if (!phy_vars_ue->pdcch_vars[0][eNB_id]->rxdataF_comp[0])
|
||||
return;
|
||||
@@ -722,7 +725,7 @@ static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
|
||||
AssertFatal(base <= nb*RX_NB_TH_MAX, "");
|
||||
oai_xygraph(graph,I,Q,base,0,10);
|
||||
}
|
||||
static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void uePdschLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PDSCH LLRs
|
||||
if (!phy_vars_ue->pdsch_vars[0][eNB_id]->llr[0])
|
||||
return;
|
||||
@@ -749,7 +752,7 @@ static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB
|
||||
//fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword);
|
||||
oai_xygraph(graph,bit,llr,base,0,10);
|
||||
}
|
||||
static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void uePdschIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
// PDSCH I/Q of MF Output
|
||||
if (!phy_vars_ue->pdsch_vars[0][eNB_id]->rxdataF_comp0[0])
|
||||
return;
|
||||
@@ -776,7 +779,7 @@ static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
||||
AssertFatal(base <= sz*RX_NB_TH_MAX, "");
|
||||
oai_xygraph(graph,I,Q,sz*RX_NB_TH_MAX,0,10);
|
||||
}
|
||||
static void uePdschThroughput (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
static void uePdschThroughput (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
/*
|
||||
float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
||||
float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
||||
@@ -869,7 +872,9 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
|
||||
fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, buf);
|
||||
return fdui;
|
||||
}
|
||||
void phy_scope_nrUE(OAI_phy_scope_t *form,
|
||||
|
||||
void phy_scope_nrUE(scopeGraphData_t **UEliveData,
|
||||
OAI_phy_scope_t *form,
|
||||
PHY_VARS_NR_UE *phy_vars_ue,
|
||||
int eNB_id,
|
||||
int UE_id) {
|
||||
@@ -886,26 +891,29 @@ void phy_scope_nrUE(OAI_phy_scope_t *form,
|
||||
int i=0;
|
||||
|
||||
while (form->graph[i].graph) {
|
||||
form->graph[i].nrUEfunct(form->graph+i, phy_vars_ue, eNB_id, UE_id);
|
||||
form->graph[i].nrUEfunct(UEliveData, form->graph+i, phy_vars_ue, eNB_id, UE_id);
|
||||
i++;
|
||||
}
|
||||
|
||||
//fl_check_forms();
|
||||
}
|
||||
|
||||
static void *nrUEscopeThread(void *arg) {
|
||||
PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg;
|
||||
size_t stksize;
|
||||
pthread_attr_t atr={0};
|
||||
pthread_attr_t atr= {0};
|
||||
pthread_attr_getstacksize(&atr, &stksize);
|
||||
pthread_attr_setstacksize(&atr,32*1024*1024 );
|
||||
int fl_argc=1;
|
||||
char *name="5G-UE-scope";
|
||||
fl_initialize (&fl_argc, &name, NULL, 0, 0);
|
||||
OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0);
|
||||
(( scopeData_t *)ue->scopeData)->liveData=calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems);
|
||||
|
||||
while (!oai_exit) {
|
||||
fl_freeze_form(form_nrue->phy_scope);
|
||||
phy_scope_nrUE(form_nrue,
|
||||
phy_scope_nrUE((( scopeData_t *)ue->scopeData)->liveData,
|
||||
form_nrue,
|
||||
ue,
|
||||
0,0);
|
||||
fl_unfreeze_form(form_nrue->phy_scope);
|
||||
@@ -915,10 +923,41 @@ static void *nrUEscopeThread(void *arg) {
|
||||
|
||||
pthread_exit((void *)arg);
|
||||
}
|
||||
|
||||
void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz) {
|
||||
scopeData_t *tmp=(scopeData_t *)ue->scopeData;
|
||||
|
||||
if (tmp) {
|
||||
scopeGraphData_t *live= ((scopeGraphData_t **)tmp->liveData)[type];
|
||||
|
||||
if (live == NULL || live->dataSize < elementSz*colSz*lineSz) {
|
||||
scopeGraphData_t *ptr=realloc(live, sizeof(scopeGraphData_t) + elementSz*colSz*lineSz);
|
||||
|
||||
if (!ptr) {
|
||||
LOG_E(PHY,"can't realloc\n");
|
||||
return;
|
||||
} else {
|
||||
live=ptr;
|
||||
}
|
||||
}
|
||||
|
||||
live->dataSize=elementSz*colSz*lineSz;
|
||||
live->elementSz=elementSz;
|
||||
live->colSz=colSz;
|
||||
live->lineSz=lineSz;
|
||||
memcpy(live+1, dataIn, elementSz*colSz*lineSz);
|
||||
((scopeGraphData_t **)tmp->liveData)[type]=live;
|
||||
}
|
||||
}
|
||||
|
||||
void nrUEinitScope(PHY_VARS_NR_UE *ue) {
|
||||
AssertFatal(ue->scopeData=malloc(sizeof(scopeData_t)),"");
|
||||
scopeData_t *scope=(scopeData_t *) ue->scopeData;
|
||||
scope->copyData=UEcopyData;
|
||||
pthread_t forms_thread;
|
||||
threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
void nrscope_autoinit(void *dataptr) {
|
||||
AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context");
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#ifndef __PHY_SCOPE_INTERFACE_H__
|
||||
#define __PHY_SCOPE_INTERFACE_H__
|
||||
#include <openair1/PHY/defs_gNB.h>
|
||||
#include <openair1/PHY/defs_nr_UE.h>
|
||||
|
||||
typedef struct {
|
||||
int *argc;
|
||||
char **argv;
|
||||
@@ -39,16 +41,25 @@ typedef struct {
|
||||
PHY_VARS_gNB *gNB;
|
||||
} scopeParms_t;
|
||||
|
||||
enum UEdataType {
|
||||
pbchDlChEstimateTime,
|
||||
pbchLlr,
|
||||
pbchRxdataF_comp,
|
||||
UEdataTypeNumberOfItems
|
||||
};
|
||||
|
||||
typedef struct scopeData_s {
|
||||
int *argc;
|
||||
char **argv;
|
||||
RU_t *ru;
|
||||
PHY_VARS_gNB *gNB;
|
||||
int32_t * rxdataF;
|
||||
void (*slotFunc)(int32_t* data, int slot, void * scopeData);
|
||||
void *liveData;
|
||||
void (*slotFunc)(int32_t *data, int slot, void *scopeData);
|
||||
void (*copyData)(PHY_VARS_NR_UE *,enum UEdataType, void *data, int elementSz, int colSz, int lineSz);
|
||||
} scopeData_t;
|
||||
|
||||
int load_softscope(char *exectype, void *initarg);
|
||||
int end_forms(void) ;
|
||||
|
||||
#define UEscopeCopy(ue, type, ...) if(ue->scopeData) ((scopeData_t*)ue->scopeData)->copyData(ue, type, ##__VA_ARGS__);
|
||||
#endif
|
||||
|
||||
@@ -837,6 +837,7 @@ typedef struct {
|
||||
/// RF and Interface devices per CC
|
||||
|
||||
openair0_device rfdevice;
|
||||
void *scopeData;
|
||||
} PHY_VARS_UE;
|
||||
|
||||
/* this structure is used to pass both UE phy vars and
|
||||
|
||||
@@ -654,40 +654,6 @@ typedef struct {
|
||||
#define PBCH_A 24
|
||||
|
||||
typedef struct {
|
||||
/// \brief Pointers to extracted PBCH symbols in frequency-domain.
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: ? [0..287] (hard coded)
|
||||
int32_t **rxdataF_ext;
|
||||
/// \brief Pointers to extracted and compensated PBCH symbols in frequency-domain.
|
||||
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
|
||||
/// - second index: ? [0..287] (hard coded)
|
||||
int32_t **rxdataF_comp;
|
||||
/// \brief Hold the channel estimates in frequency domain.
|
||||
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
|
||||
/// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
|
||||
int32_t **dl_ch_estimates;
|
||||
/// \brief Pointers to downlink channel estimates in frequency-domain extracted in PRBS.
|
||||
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
|
||||
/// - second index: ? [0..287] (hard coded)
|
||||
int32_t **dl_ch_estimates_ext;
|
||||
/// \brief Hold the channel estimates in time domain (used for tracking).
|
||||
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
|
||||
/// - second index: samples? [0..2*ofdm_symbol_size[
|
||||
int32_t **dl_ch_estimates_time;
|
||||
int log2_maxh;
|
||||
uint8_t pbch_a[NR_POLAR_PBCH_PAYLOAD_BITS>>3];
|
||||
uint32_t pbch_a_interleaved;
|
||||
uint32_t pbch_a_prime;
|
||||
uint8_t pbch_e[NR_POLAR_PBCH_E];
|
||||
int16_t demod_pbch_e[NR_POLAR_PBCH_E];
|
||||
/// \brief Pointer to PBCH llrs.
|
||||
/// - first index: ? [0..1919] (hard coded)
|
||||
int16_t *llr;
|
||||
/// \brief Pointer to PBCH decoded output.
|
||||
/// - first index: ? [0..63] (hard coded)
|
||||
uint8_t *decoded_output;
|
||||
/// \brief PBCH additional bits
|
||||
uint8_t xtra_byte;
|
||||
/// \brief Total number of PDU errors.
|
||||
uint32_t pdu_errors;
|
||||
/// \brief Total number of PDU errors 128 frames ago.
|
||||
@@ -695,7 +661,7 @@ typedef struct {
|
||||
/// \brief Total number of consecutive PDU errors.
|
||||
uint32_t pdu_errors_conseq;
|
||||
/// \brief FER (in percent) .
|
||||
uint32_t pdu_fer;
|
||||
//uint32_t pdu_fer;
|
||||
} NR_UE_PBCH;
|
||||
|
||||
typedef struct {
|
||||
@@ -1073,7 +1039,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
int dl_stats[5];
|
||||
|
||||
void* scopeData;
|
||||
} PHY_VARS_NR_UE;
|
||||
|
||||
/* this structure is used to pass both UE phy vars and
|
||||
|
||||
@@ -82,6 +82,11 @@
|
||||
#define DAQ_AGC_OFF 0
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t decoded_output[64];
|
||||
uint8_t xtra_byte;
|
||||
} fapiPbch_t;
|
||||
|
||||
/** @addtogroup _PHY_PROCEDURES_
|
||||
* @{
|
||||
*/
|
||||
@@ -395,7 +400,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc);
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void * typeSpecific);
|
||||
|
||||
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -118,7 +118,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc ){
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void * typeSpecific){
|
||||
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
@@ -162,8 +163,11 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8;
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB:
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output;
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte;
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu=malloc(sizeof(((fapiPbch_t*)typeSpecific)->decoded_output));
|
||||
memcpy(rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu,
|
||||
((fapiPbch_t*)typeSpecific)->decoded_output,
|
||||
sizeof(((fapiPbch_t*)typeSpecific)->decoded_output));
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ((fapiPbch_t*)typeSpecific)->xtra_byte;
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7;
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax;
|
||||
rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell;
|
||||
@@ -353,10 +357,9 @@ void nr_ue_measurement_procedures(uint16_t l,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
}
|
||||
|
||||
void nr_ue_pbch_procedures(uint8_t gNB_id,
|
||||
static void nr_ue_pbch_procedures(uint8_t gNB_id,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t abstraction_flag)
|
||||
UE_nr_rxtx_proc_t *proc,int estimateSz, struct complex16 dl_ch_estimates[][estimateSz])
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -368,13 +371,15 @@ void nr_ue_pbch_procedures(uint8_t gNB_id,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);
|
||||
|
||||
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id);
|
||||
|
||||
fapiPbch_t result;
|
||||
ret = nr_rx_pbch(ue, proc,
|
||||
estimateSz, dl_ch_estimates,
|
||||
ue->pbch_vars[gNB_id],
|
||||
&ue->frame_parms,
|
||||
gNB_id,
|
||||
(ue->frame_parms.ssb_index)&7,
|
||||
SISO);
|
||||
SISO,
|
||||
&result);
|
||||
|
||||
if (ret==0) {
|
||||
|
||||
@@ -444,7 +449,6 @@ void nr_ue_pbch_procedures(uint8_t gNB_id,
|
||||
}
|
||||
|
||||
if (frame_rx % 100 == 0) {
|
||||
ue->pbch_vars[gNB_id]->pdu_fer = ue->pbch_vars[gNB_id]->pdu_errors - ue->pbch_vars[gNB_id]->pdu_errors_last;
|
||||
ue->pbch_vars[gNB_id]->pdu_errors_last = ue->pbch_vars[gNB_id]->pdu_errors;
|
||||
}
|
||||
|
||||
@@ -795,16 +799,16 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
switch (pdsch) {
|
||||
case RA_PDSCH:
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, NULL, number_pdus, proc);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, NULL, number_pdus, proc, NULL);
|
||||
ue->UE_mode[gNB_id] = RA_RESPONSE;
|
||||
break;
|
||||
case PDSCH:
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, NULL, number_pdus, proc);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, NULL, number_pdus, proc, NULL);
|
||||
break;
|
||||
case SI_PDSCH:
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, NULL, number_pdus, proc);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, NULL, number_pdus, proc, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1400,6 +1404,9 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
|
||||
if (slot_ssb) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_IN);
|
||||
LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
|
||||
const int estimateSz=7*2*sizeof(int)*fp->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[fp->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[fp->nb_antennas_rx][estimateSz];
|
||||
for (int i=1; i<4; i++) {
|
||||
|
||||
nr_slot_fep(ue,
|
||||
@@ -1409,7 +1416,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
|
||||
|
||||
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
nr_pbch_channel_estimation(ue,proc,gNB_id,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit);
|
||||
nr_pbch_channel_estimation(ue, estimateSz, dl_ch_estimates, dl_ch_estimates_time,proc,gNB_id,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit);
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
}
|
||||
|
||||
@@ -1418,13 +1425,14 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
|
||||
if ((ue->decode_MIB == 1) && slot_pbch) {
|
||||
|
||||
LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
|
||||
nr_ue_pbch_procedures(gNB_id, ue, proc, 0);
|
||||
nr_ue_pbch_procedures(gNB_id, ue, proc, estimateSz, dl_ch_estimates);
|
||||
|
||||
if (ue->no_timing_correction==0) {
|
||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||
nr_adjust_synch_ue(fp,
|
||||
ue,
|
||||
gNB_id,
|
||||
estimateSz, dl_ch_estimates_time,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
|
||||
|
||||
int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return(0); }
|
||||
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); }
|
||||
int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); }
|
||||
@@ -35,4 +36,5 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc) {}
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void * typeSpecific ) {}
|
||||
|
||||
@@ -438,6 +438,7 @@ int main(int argc, char **argv)
|
||||
|
||||
printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL);
|
||||
|
||||
|
||||
RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
|
||||
RC.gNB[0] = malloc16_clear(sizeof(*(RC.gNB[0])));
|
||||
gNB = RC.gNB[0];
|
||||
@@ -531,13 +532,13 @@ int main(int argc, char **argv)
|
||||
s_im = malloc(2*sizeof(double*));
|
||||
r_re = malloc(2*sizeof(double*));
|
||||
r_im = malloc(2*sizeof(double*));
|
||||
txdata = malloc(2*sizeof(int*));
|
||||
txdata = calloc(2,sizeof(int*));
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
|
||||
|
||||
s_re[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
s_im[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
|
||||
r_re[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_im[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
|
||||
@@ -550,6 +551,7 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
//configure UE
|
||||
|
||||
UE = malloc16_clear(sizeof(*UE));
|
||||
memcpy(&UE->frame_parms,frame_parms,sizeof(UE->frame_parms));
|
||||
//phy_init_nr_top(UE); //called from init_nr_ue_signal
|
||||
@@ -722,6 +724,9 @@ int main(int argc, char **argv)
|
||||
UE_nr_rxtx_proc_t proc={0};
|
||||
UE->rx_offset=0;
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz=7*2*sizeof(int)*frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][estimateSz];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++; // to select the first transmitted ssb
|
||||
UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms,ssb_index);
|
||||
|
||||
@@ -732,17 +737,20 @@ int main(int argc, char **argv)
|
||||
i%frame_parms->symbols_per_slot,
|
||||
ssb_slot);
|
||||
|
||||
nr_pbch_channel_estimation(UE,&proc,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf);
|
||||
nr_pbch_channel_estimation(UE,estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf);
|
||||
|
||||
}
|
||||
|
||||
fapiPbch_t result;
|
||||
ret = nr_rx_pbch(UE,
|
||||
&proc,
|
||||
UE->pbch_vars[0],
|
||||
estimateSz, dl_ch_estimates,
|
||||
UE->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
ssb_index%8,
|
||||
SISO);
|
||||
SISO,
|
||||
&result);
|
||||
|
||||
if (ret==0) {
|
||||
//UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically
|
||||
@@ -751,9 +759,9 @@ int main(int argc, char **argv)
|
||||
for (int i=0; i<8; i++)
|
||||
gNB_xtra_byte |= ((gNB->pbch.pbch_a>>(31-i))&1)<<(7-i);
|
||||
|
||||
payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte);
|
||||
payload_ret = (result.xtra_byte == gNB_xtra_byte);
|
||||
for (i=0;i<3;i++){
|
||||
payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
|
||||
payload_ret += (result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
|
||||
}
|
||||
//printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte);
|
||||
//printf("ret %d\n", payload_ret);
|
||||
|
||||
@@ -82,7 +82,9 @@ void nr_fill_nfapi_pucch(module_id_t mod_id,
|
||||
NR_BWP_UplinkDedicated_t *ubwpd;
|
||||
ubwpd = cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP:NULL;
|
||||
|
||||
LOG_D(NR_MAC,"pucch_acknak: %d.%d Calling nr_configure_pucch (ubwpd %p,r_pucch %d) pucch in %d.%d\n",frame,slot,ubwpd,pucch->r_pucch,pucch->frame,pucch->ul_slot);
|
||||
LOG_D(NR_MAC,"%d.%d Calling nr_configure_pucch (ubwpd %p,r_pucch %d) pucch to be scheduled in %d.%d\n",
|
||||
frame,slot,ubwpd,pucch->r_pucch,pucch->frame,pucch->ul_slot);
|
||||
|
||||
nr_configure_pucch(pucch_pdu,
|
||||
scc,
|
||||
UE_info->CellGroup[UE_id],
|
||||
@@ -1883,12 +1885,13 @@ void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot)
|
||||
}
|
||||
curr_pucch->sr_flag = true;
|
||||
} else {
|
||||
NR_sched_pucch_t sched_sr;
|
||||
memset(&sched_sr, 0, sizeof(sched_sr));
|
||||
sched_sr.frame = SFN;
|
||||
sched_sr.ul_slot = slot;
|
||||
sched_sr.resource_indicator = found;
|
||||
sched_sr.sr_flag = true;
|
||||
NR_sched_pucch_t sched_sr = {
|
||||
.frame = SFN,
|
||||
.ul_slot = slot,
|
||||
.sr_flag = true,
|
||||
.resource_indicator = found,
|
||||
.r_pucch = -1
|
||||
};
|
||||
nr_fill_nfapi_pucch(Mod_idP, SFN, slot, &sched_sr, UE_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1236,7 +1236,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
|
||||
(dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length,
|
||||
(dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier,
|
||||
(dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB;
|
||||
|
||||
free((dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu);
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SIB:
|
||||
ret_mask |= (handle_bcch_dlsch(dl_info->module_id,
|
||||
|
||||
@@ -4297,6 +4297,7 @@ ssize_t do_nrMeasurementReport(uint8_t *buffer,
|
||||
If we delete this asn1cCalloc statement, eNB will crash in NSA mode.
|
||||
Please don't delete the following line unless the bug has been found. */
|
||||
asn1cCalloc(measresulteutra_list->cgi_Info, measresult_cgi2);
|
||||
(void) measresult_cgi2;
|
||||
struct LTE_MeasResultEUTRA__measResult* measResult= &measresulteutra_list->measResult;
|
||||
asn1cCallocOne(measResult->rsrpResult, rsrp_tar);
|
||||
asn1cCallocOne(measResult->rsrqResult, rsrq_tar);
|
||||
|
||||
@@ -905,30 +905,27 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(
|
||||
for (pdusession = 0; pdusession < ue_context_pP->ue_context.setup_pdu_sessions; pdusession++) {
|
||||
// if (xid == ue_context_pP->ue_context.pdusession[pdusession].xid) {
|
||||
if (ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_DONE) {
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id;
|
||||
// NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].pdusession_id = 1;
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].nb_of_qos_flow = ue_context_pP->ue_context.pduSession[pdusession].param.nb_qos;
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gtp_teid = ue_context_pP->ue_context.gnb_gtp_teid[pdusession];
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.pdu_session_type = PDUSessionType_ipv4;
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.length = ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].length;
|
||||
memcpy(NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.buffer,
|
||||
ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].buffer, sizeof(uint8_t)*20);
|
||||
for (qos_flow_index = 0; qos_flow_index < NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].nb_of_qos_flow; qos_flow_index++) {
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi =
|
||||
pdusession_setup_t * tmp=&NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession];
|
||||
tmp->pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id;
|
||||
// tmp->pdusession_id = 1;
|
||||
tmp->nb_of_qos_flow = ue_context_pP->ue_context.pduSession[pdusession].param.nb_qos;
|
||||
tmp->gtp_teid = ue_context_pP->ue_context.gnb_gtp_teid[pdusession];
|
||||
tmp->gNB_addr.pdu_session_type = PDUSessionType_ipv4;
|
||||
tmp->gNB_addr.length = ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].length;
|
||||
memcpy(tmp->gNB_addr.buffer,
|
||||
ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].buffer, tmp->gNB_addr.length);
|
||||
for (qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) {
|
||||
tmp->associated_qos_flows[qos_flow_index].qfi =
|
||||
ue_context_pP->ue_context.pduSession[pdusession].param.qos[qos_flow_index].qfi;
|
||||
NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
}
|
||||
|
||||
ue_context_pP->ue_context.pduSession[pdusession].status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
LOG_I (NR_RRC,"gnb_gtp_addr (msg index %d, pdu_sessions index %d, status %d, xid %d): nb_of_pdusessions %d, pdusession_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
|
||||
LOG_I (NR_RRC,"gnb_gtp_addr (msg index %d, pdu_sessions index %d, status %d, xid %d): nb_of_pdusessions %d, pdusession_id %d, teid: %u \n ",
|
||||
pdu_sessions_done, pdusession, ue_context_pP->ue_context.pduSession[pdusession].status, xid,
|
||||
ue_context_pP->ue_context.nb_of_pdusessions,
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].pdusession_id,
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gtp_teid,
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[0],
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[1],
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[2],
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[3]);
|
||||
NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gtp_teid);
|
||||
pdu_sessions_done++;
|
||||
} else if ((ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_NEW) ||
|
||||
(ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_ESTABLISHED)) {
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user