Merge remote-tracking branch 'origin/develop' into NR_handling_PMI_report
This commit is contained in:
@@ -353,9 +353,18 @@ typedef struct pdusession_tobeswitched_s {
|
||||
uint32_t gtp_teid;
|
||||
} pdusession_tobeswitched_t;
|
||||
|
||||
typedef struct qos_flow_tobe_modified_s {
|
||||
uint8_t qfi; // 0~63
|
||||
} qos_flow_tobe_modified_t;
|
||||
|
||||
typedef struct pdusession_modify_s {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
uint8_t pdusession_id;
|
||||
|
||||
uint8_t nb_of_qos_flow;
|
||||
|
||||
// qos_flow_add_or_modify
|
||||
qos_flow_tobe_modified_t qos[QOSFLOW_MAX_VALUE];
|
||||
} pdusession_modify_t;
|
||||
|
||||
typedef enum ngap_Cause_e {
|
||||
@@ -821,7 +830,7 @@ typedef struct ngap_pdusession_modify_req_s {
|
||||
/* Number of pdusession to be modify in the list */
|
||||
uint8_t nb_pdusessions_tomodify;
|
||||
|
||||
/* E RAB modify request */
|
||||
/* pdu session modify request */
|
||||
pdusession_t pdusession_modify_params[NGAP_MAX_PDUSESSION];
|
||||
} ngap_pdusession_modify_req_t;
|
||||
|
||||
|
||||
@@ -401,6 +401,12 @@ typedef struct NbIoTRrcConfigurationReq_s {
|
||||
long ue_TimersAndConstants_n311_NB;
|
||||
} NbIoTRrcConfigurationReq;
|
||||
|
||||
typedef struct {
|
||||
int N1;
|
||||
int N2;
|
||||
int XP;
|
||||
} rrc_pdsch_AntennaPorts_t;
|
||||
|
||||
// gNB: GNB_APP -> RRC messages
|
||||
typedef struct NRRrcConfigurationReq_s {
|
||||
uint64_t cell_identity;
|
||||
@@ -413,13 +419,12 @@ typedef struct NRRrcConfigurationReq_s {
|
||||
NR_ServingCellConfig_t *scd;
|
||||
int ssb_SubcarrierOffset;
|
||||
int sib1_tda;
|
||||
int pdsch_AntennaPorts_N1;
|
||||
int pdsch_AntennaPorts_N2;
|
||||
int pdsch_AntennaPorts_XP;
|
||||
rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
||||
int pusch_AntennaPorts;
|
||||
int minRXTXTIME;
|
||||
int do_CSIRS;
|
||||
int do_SRS;
|
||||
bool force_256qam_off;
|
||||
int pusch_TargetSNRx10;
|
||||
int pucch_TargetSNRx10;
|
||||
} gNB_RrcConfigurationReq;
|
||||
|
||||
@@ -627,15 +627,18 @@ void RCconfig_NR_L1(void) {
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
if (ulprbbl) LOG_I(NR_PHY,"PRB blacklist %s\n",ulprbbl);
|
||||
char *pt = strtok(ulprbbl,",");
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
int prbbl[275];
|
||||
int num_prbbl=0;
|
||||
memset(prbbl,0,275*sizeof(int));
|
||||
|
||||
while (pt) {
|
||||
prbbl[atoi(pt)] = 1;
|
||||
const int rb = atoi(pt);
|
||||
AssertFatal(rb < 275, "RB %d out of bounds (max 275)\n", rb);
|
||||
prbbl[rb] = 0x3FFF; // all symbols taken
|
||||
LOG_I(NR_PHY,"Blacklisting prb %d\n",atoi(pt));
|
||||
pt = strtok(NULL,",");
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
|
||||
@@ -742,15 +745,16 @@ void RCconfig_nr_macrlc() {
|
||||
|
||||
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
char *pt = strtok(ulprbbl,",");
|
||||
int prbbl[275];
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
uint16_t prbbl[275];
|
||||
int num_prbbl=0;
|
||||
int prb;
|
||||
memset(prbbl,0,275*sizeof(int));
|
||||
memset(prbbl,0,sizeof(prbbl));
|
||||
while (pt) {
|
||||
prb=atoi(pt);
|
||||
prbbl[prb] = 1;
|
||||
pt = strtok(NULL,",");
|
||||
const int prb = atoi(pt);
|
||||
AssertFatal(prb < 275, "RB %d out of bounds (max 275)\n", prb);
|
||||
prbbl[prb] = 0x3FFF; // all symbols taken
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
|
||||
@@ -1169,11 +1173,11 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
LOG_I(RRC,"SSB SCO %d\n",*GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = *GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr;
|
||||
LOG_I(RRC,"pdsch_AntennaPorts N1 %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts_N1 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts.N1 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
LOG_I(RRC,"pdsch_AntennaPorts N2 %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts_N2 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts.N2 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
LOG_I(RRC,"pdsch_AntennaPorts XP %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts_XP = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts.XP = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
LOG_I(RRC,"pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr;
|
||||
LOG_I(RRC,"minTXRXTIME %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIME_IDX].iptr);
|
||||
@@ -1182,8 +1186,10 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
|
||||
LOG_I(RRC,"Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
|
||||
printf("Do SRS %d\n",*GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr);
|
||||
LOG_I(RRC, "Do SRS %d\n",*GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).do_SRS = *GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).force_256qam_off = *GNBParamList.paramarray[i][GNB_FORCE256QAMOFF_IDX].iptr;
|
||||
LOG_I(RRC, "256 QAM: %s\n", NRRRC_CONFIGURATION_REQ (msg_p).force_256qam_off ? "force off" : "may be on");
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).scc = scc;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).scd = scd;
|
||||
|
||||
@@ -1468,7 +1474,8 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) {
|
||||
|
||||
// NGAP_REGISTER_GNB_REQ (msg_p).enb_interface_name_for_NGU = strdup(enb_interface_name_for_NGU);
|
||||
cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr);
|
||||
address = strtok(cidr, "/");
|
||||
char *save = NULL;
|
||||
address = strtok_r(cidr, "/", &save);
|
||||
|
||||
NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv6 = 0;
|
||||
NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4 = 1;
|
||||
@@ -1740,7 +1747,8 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
|
||||
}
|
||||
|
||||
cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr);
|
||||
address = strtok(cidr, "/");
|
||||
char *save = NULL;
|
||||
address = strtok_r(cidr, "/", &save);
|
||||
X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0;
|
||||
X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1;
|
||||
strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address);
|
||||
@@ -2045,13 +2053,9 @@ void configure_gnb_du_mac(int inst) {
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[inst];
|
||||
// LOG_I(GNB_APP,"Configuring MAC/L1 %d, carrier->sib2 %p\n", inst, &carrier->sib2->radioResourceConfigCommon);
|
||||
LOG_I(GNB_APP,"Configuring gNB DU MAC/L1 %d \n", inst);
|
||||
rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
||||
pdsch_AntennaPorts.N1 = rrc->configuration.pdsch_AntennaPorts_N1;
|
||||
pdsch_AntennaPorts.N2 = rrc->configuration.pdsch_AntennaPorts_N2;
|
||||
pdsch_AntennaPorts.XP = rrc->configuration.pdsch_AntennaPorts_XP;
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
pdsch_AntennaPorts,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
|
||||
@@ -124,8 +124,11 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_NRCELLID "nr_cellid"
|
||||
#define GNB_CONFIG_STRING_MINRXTXTIME "min_rxtxtime"
|
||||
#define GNB_CONFIG_STRING_ULPRBBLACKLIST "ul_prbblacklist"
|
||||
#define GNB_CONFIG_STRING_FORCE256QAMOFF "force_256qam_off"
|
||||
|
||||
|
||||
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* cell configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -146,16 +149,17 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0, iptr:NULL, defintval:31, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N1, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N2, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_XP, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N1, "horiz. log. antenna ports", 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N2, "vert. log. antenna ports", 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_XP, "XP log. antenna ports", 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_PUSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_SIB1TDA, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_DOSRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \
|
||||
{GNB_CONFIG_STRING_MINRXTXTIME, NULL, 0, iptr:NULL, defintval:2, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0} \
|
||||
{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0}, \
|
||||
{GNB_CONFIG_STRING_FORCE256QAMOFF, GNB_CONFIG_HLP_FORCE256QAMOFF, PARAMFLAG_BOOL, iptr:NULL, defintval:0, TYPE_INT, 0} \
|
||||
}
|
||||
|
||||
#define GNB_GNB_ID_IDX 0
|
||||
@@ -183,6 +187,7 @@ typedef enum {
|
||||
#define GNB_NRCELLID_IDX 22
|
||||
#define GNB_MINRXTXTIME_IDX 23
|
||||
#define GNB_ULPRBBLACKLIST_IDX 24
|
||||
#define GNB_FORCE256QAMOFF_IDX 25
|
||||
|
||||
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
|
||||
#define GNBPARAMS_CHECK { \
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
#include "nfapi_interface.h"
|
||||
#include "PHY_INTERFACE/IF_Module.h"
|
||||
|
||||
#include "PHY/TOOLS/time_meas.h"
|
||||
#include "time_meas.h"
|
||||
|
||||
#include "PHY/defs_common.h" // for PRACH_RESOURCES_t
|
||||
#include "PHY/LTE_TRANSPORT/transport_common.h"
|
||||
|
||||
@@ -315,21 +315,21 @@ void get_info_from_tda_tables(int default_abc,
|
||||
int tda,
|
||||
int dmrs_TypeA_Position,
|
||||
int normal_CP,
|
||||
bool *is_mapping_typeA,
|
||||
int *startSymbolIndex,
|
||||
int *nrOfSymbols) {
|
||||
int k0 = 0;
|
||||
int is_mapping_typeA = 1;
|
||||
switch(default_abc){
|
||||
case 1:
|
||||
if (normal_CP){
|
||||
if (dmrs_TypeA_Position){
|
||||
is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][0];
|
||||
k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][3];
|
||||
}
|
||||
else{
|
||||
is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][0];
|
||||
k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][3];
|
||||
@@ -337,13 +337,13 @@ void get_info_from_tda_tables(int default_abc,
|
||||
}
|
||||
else{
|
||||
if (dmrs_TypeA_Position){
|
||||
is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][0];
|
||||
k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][3];
|
||||
}
|
||||
else{
|
||||
is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][0];
|
||||
k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][3];
|
||||
@@ -352,13 +352,13 @@ void get_info_from_tda_tables(int default_abc,
|
||||
break;
|
||||
case 2:
|
||||
if (dmrs_TypeA_Position){
|
||||
is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][0];
|
||||
k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][3];
|
||||
}
|
||||
else{
|
||||
is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][0];
|
||||
k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][3];
|
||||
@@ -366,13 +366,13 @@ void get_info_from_tda_tables(int default_abc,
|
||||
break;
|
||||
case 3:
|
||||
if (dmrs_TypeA_Position){
|
||||
is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][0];
|
||||
k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][3];
|
||||
}
|
||||
else{
|
||||
is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][0];
|
||||
*is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][0];
|
||||
k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][1];
|
||||
*startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][2];
|
||||
*nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][3];
|
||||
@@ -382,7 +382,6 @@ void get_info_from_tda_tables(int default_abc,
|
||||
AssertFatal(1==0,"Invalid default time domaing allocation type\n");
|
||||
}
|
||||
AssertFatal(k0==0,"Only k0 = 0 is supported\n");
|
||||
AssertFatal(is_mapping_typeA==1,"Only mapping type A is currently supported\n");
|
||||
}
|
||||
|
||||
const char *prachfmt[]={"0","1","2","3", "A1","A2","A3","B1","B4","C0","C2","A1/B1","A2/B2","A3/B3"};
|
||||
@@ -2721,6 +2720,7 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
LOG_D(NR_MAC,"DAI1 nbits %d\n",dci_pdu->dai[0].nbits);
|
||||
// 2nd DAI
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that
|
||||
dci_pdu->dai[1].nbits = 2;
|
||||
size += dci_pdu->dai[1].nbits;
|
||||
@@ -2991,7 +2991,8 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
dci_pdu->srs_request.nbits = 3;
|
||||
size += dci_pdu->srs_request.nbits;
|
||||
// CBGTI
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig&&
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) {
|
||||
uint8_t maxCBGperTB = (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock + 1) * 2;
|
||||
long *maxCWperDCI_rrc = pdsch_Config->maxNrofCodeWordsScheduledByDCI;
|
||||
@@ -3336,65 +3337,65 @@ uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i
|
||||
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
NR_NZP_CSI_RS_Resource_t *nzpcsi,
|
||||
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period, int *offset) {
|
||||
|
||||
if(nzpcsi != NULL) {
|
||||
if(periodicityAndOffset != NULL) {
|
||||
|
||||
NR_CSI_ResourcePeriodicityAndOffset_PR p_and_o = nzpcsi->periodicityAndOffset->present;
|
||||
NR_CSI_ResourcePeriodicityAndOffset_PR p_and_o = periodicityAndOffset->present;
|
||||
|
||||
switch(p_and_o){
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots4:
|
||||
*period = 4;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots4;
|
||||
*offset = periodicityAndOffset->choice.slots4;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots5:
|
||||
*period = 5;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots5;
|
||||
*offset = periodicityAndOffset->choice.slots5;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots8:
|
||||
*period = 8;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots8;
|
||||
*offset = periodicityAndOffset->choice.slots8;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots10:
|
||||
*period = 10;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots10;
|
||||
*offset = periodicityAndOffset->choice.slots10;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots16:
|
||||
*period = 16;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots16;
|
||||
*offset = periodicityAndOffset->choice.slots16;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots20:
|
||||
*period = 20;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots20;
|
||||
*offset = periodicityAndOffset->choice.slots20;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots32:
|
||||
*period = 32;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots32;
|
||||
*offset = periodicityAndOffset->choice.slots32;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots40:
|
||||
*period = 40;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots40;
|
||||
*offset = periodicityAndOffset->choice.slots40;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots64:
|
||||
*period = 64;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots64;
|
||||
*offset = periodicityAndOffset->choice.slots64;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots80:
|
||||
*period = 80;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots80;
|
||||
*offset = periodicityAndOffset->choice.slots80;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots160:
|
||||
*period = 160;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots160;
|
||||
*offset = periodicityAndOffset->choice.slots160;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots320:
|
||||
*period = 320;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots320;
|
||||
*offset = periodicityAndOffset->choice.slots320;
|
||||
break;
|
||||
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots640:
|
||||
*period = 640;
|
||||
*offset = nzpcsi->periodicityAndOffset->choice.slots640;
|
||||
*offset = periodicityAndOffset->choice.slots640;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"No periodicity and offset found in CSI resource");
|
||||
|
||||
@@ -140,6 +140,7 @@ void get_info_from_tda_tables(int default_abc,
|
||||
int tda,
|
||||
int dmrs_TypeA_Position,
|
||||
int normal_CP,
|
||||
bool *is_mapping_typeA,
|
||||
int *startSymbolIndex,
|
||||
int *nrOfSymbols);
|
||||
|
||||
@@ -160,7 +161,7 @@ int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH);
|
||||
void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset);
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
NR_NZP_CSI_RS_Resource_t *nzpcsi,
|
||||
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||
int *period, int *offset);
|
||||
|
||||
void reverse_n_bits(uint8_t *value, uint16_t bitlen);
|
||||
|
||||
@@ -214,6 +214,7 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
PUCCH_sched_t *pucch,
|
||||
int csi_report_id,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig);
|
||||
|
||||
uint8_t get_rsrp_index(int rsrp);
|
||||
@@ -271,6 +272,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
|
||||
NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
|
||||
int *mappingtype,
|
||||
uint8_t time_domain_ind,
|
||||
int default_abc,
|
||||
bool use_default);
|
||||
@@ -350,6 +352,8 @@ and fills the PRACH PDU per each FD occasion.
|
||||
*/
|
||||
void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id);
|
||||
void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, int thread_id);
|
||||
void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot);
|
||||
void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot);
|
||||
|
||||
/* \brief This function schedules the Msg3 transmission
|
||||
@param
|
||||
|
||||
@@ -470,6 +470,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
|
||||
NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
|
||||
int *mapping_type,
|
||||
uint8_t time_domain_ind,
|
||||
int default_abc,
|
||||
bool use_default){
|
||||
@@ -547,13 +548,15 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
else {// Default configuration from tables
|
||||
|
||||
bool is_typeA;
|
||||
get_info_from_tda_tables(default_abc,
|
||||
time_domain_ind,
|
||||
dmrs_typeA_pos,
|
||||
1, // normal CP
|
||||
&is_typeA,
|
||||
&sliv_S,
|
||||
&sliv_L);
|
||||
|
||||
*mapping_type = is_typeA? typeA : typeB;
|
||||
dlsch_config_pdu->number_symbols = sliv_L;
|
||||
dlsch_config_pdu->start_symbol = sliv_S;
|
||||
}
|
||||
@@ -859,12 +862,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
else if (mac->scc_SIB && mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup)
|
||||
pdsch_TimeDomainAllocationList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||||
|
||||
int mappingtype;
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val,default_abc,rnti==SI_RNTI) < 0) {
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,
|
||||
NULL,dlsch_config_pdu_1_0,&mappingtype,
|
||||
dci->time_domain_assignment.val,
|
||||
default_abc,rnti==SI_RNTI) < 0) {
|
||||
LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
|
||||
return -1;
|
||||
}
|
||||
int mappingtype = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType : ((dlsch_config_pdu_1_0->start_symbol <= 3)? typeA: typeB);
|
||||
if(pdsch_TimeDomainAllocationList && rnti!=SI_RNTI)
|
||||
mappingtype = pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType;
|
||||
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
|
||||
@@ -1056,13 +1064,16 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
return -1;
|
||||
}
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
int mappingtype;
|
||||
NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = choose_dl_tda_list(pdsch_Config,bwpc->pdsch_ConfigCommon->choice.setup);
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val,0,false) < 0) {
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,
|
||||
NULL,dlsch_config_pdu_1_1,&mappingtype,
|
||||
dci->time_domain_assignment.val,0,false) < 0) {
|
||||
LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mappingtype = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType : ((dlsch_config_pdu_1_1->start_symbol <= 3)? typeA: typeB);
|
||||
if(pdsch_TimeDomainAllocationList)
|
||||
mappingtype = pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType;
|
||||
|
||||
dlsch_config_pdu_1_1->dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2;
|
||||
|
||||
@@ -2392,7 +2403,7 @@ uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac,
|
||||
"CSI resource not found among PUCCH resources\n");
|
||||
|
||||
pucch->resource_indicator = found;
|
||||
csi_bits = nr_get_csi_payload(mac, pucch, csi_measconfig);
|
||||
csi_bits += nr_get_csi_payload(mac, pucch, csi_report_id, csi_measconfig);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2406,31 +2417,30 @@ uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
||||
PUCCH_sched_t *pucch,
|
||||
int csi_report_id,
|
||||
NR_CSI_MeasConfig_t *csi_MeasConfig) {
|
||||
|
||||
int n_csi_bits = 0;
|
||||
|
||||
AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count>0,"No CSI Report configuration available\n");
|
||||
|
||||
for (int csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
|
||||
switch(csi_reportconfig->reportQuantity.present) {
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_none:
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
|
||||
n_csi_bits += get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig);
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
|
||||
AssertFatal(1==0,"Measurement report based on CSI-RS not availalble\n");
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present);
|
||||
}
|
||||
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
|
||||
switch(csi_reportconfig->reportQuantity.present) {
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_none:
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
|
||||
n_csi_bits = get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig);
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
|
||||
AssertFatal(1==0,"Measurement report based on CSI-RS not availalble\n");
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present);
|
||||
}
|
||||
return (n_csi_bits);
|
||||
}
|
||||
@@ -3832,6 +3842,21 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
|
||||
LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID);
|
||||
rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
|
||||
ra->RA_RAPID_found = 1;
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
/* When we are emulating L1 with multiple UEs, the rx_indication will have
|
||||
multiple RAR PDUs. The code would previously handle each of these PDUs,
|
||||
but it should only be handling the single RAR that matches the current
|
||||
UE. */
|
||||
LOG_I(NR_MAC, "RAR PDU found for our UE with PDU index %d\n", pdu_id);
|
||||
dl_info->rx_ind->number_pdus = 1;
|
||||
if (pdu_id != 0) {
|
||||
memcpy(&dl_info->rx_ind->rx_indication_body[0],
|
||||
&dl_info->rx_ind->rx_indication_body[pdu_id],
|
||||
sizeof(fapi_nr_rx_indication_body_t));
|
||||
}
|
||||
mac->nr_ue_emul_l1.expected_rar = false;
|
||||
memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(mac->nr_ue_emul_l1.index_has_rar));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (rarh->E == 0) {
|
||||
|
||||
@@ -768,7 +768,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
return -1;
|
||||
}
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_TimeDomainAllocationList, NULL, pusch_config_pdu, NULL, dci->time_domain_assignment.val,0,false) < 0) {
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_TimeDomainAllocationList, NULL, pusch_config_pdu, NULL, NULL, dci->time_domain_assignment.val,0,false) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1046,6 +1046,10 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
nr_dcireq_t dcireq;
|
||||
|
||||
if(mac->cg != NULL){ // we have a cg
|
||||
|
||||
nr_schedule_csirs_reception(mac, rx_frame, rx_slot);
|
||||
nr_schedule_csi_for_im(mac, rx_frame, rx_slot);
|
||||
|
||||
dcireq.module_id = mod_id;
|
||||
dcireq.gNB_index = gNB_index;
|
||||
dcireq.cc_id = cc_id;
|
||||
@@ -1115,7 +1119,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
tx_req.number_of_pdus = 0;
|
||||
|
||||
for (int j = 0; j < ul_config->number_pdus; j++) {
|
||||
uint8_t *ulsch_input_buffer = &(ulsch_input_buffer_array[tx_req.number_of_pdus][MAX_ULSCH_PAYLOAD_BYTES]);
|
||||
uint8_t *ulsch_input_buffer = ulsch_input_buffer_array[tx_req.number_of_pdus];
|
||||
|
||||
fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = &ul_config->ul_config_list[j];
|
||||
|
||||
@@ -2307,7 +2311,6 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in
|
||||
return;
|
||||
|
||||
if (N_UCI > 0) {
|
||||
|
||||
LOG_D(NR_MAC,"%d.%d configure pucch, O_SR %d, O_ACK %d, O_CSI %d\n",frameP,slotP,O_SR,O_ACK,O_CSI);
|
||||
pucch->resource_set_id = find_pucch_resource_set(mac, O_ACK + O_CSI);
|
||||
select_pucch_resource(mac, pucch);
|
||||
@@ -2331,9 +2334,206 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) {
|
||||
|
||||
if (mac->ra.ra_state != RA_SUCCEEDED && get_softmodem_params()->phy_test == 0)
|
||||
return;
|
||||
|
||||
NR_CellGroupConfig_t *CellGroup = mac->cg;
|
||||
|
||||
if (!CellGroup || !CellGroup->spCellConfig || !CellGroup->spCellConfig->spCellConfigDedicated ||
|
||||
!CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig)
|
||||
return;
|
||||
|
||||
NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
|
||||
|
||||
if (csi_measconfig->csi_IM_ResourceToAddModList == NULL)
|
||||
return;
|
||||
|
||||
fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
|
||||
NR_CSI_IM_Resource_t *imcsi;
|
||||
int period, offset;
|
||||
NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id;
|
||||
int mu = mac->DLbwp[dl_bwp_id-1] ?
|
||||
mac->DLbwp[dl_bwp_id-1]->bwp_Common->genericParameters.subcarrierSpacing :
|
||||
mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing;
|
||||
|
||||
for (int id = 0; id < csi_measconfig->csi_IM_ResourceToAddModList->list.count; id++){
|
||||
imcsi = csi_measconfig->csi_IM_ResourceToAddModList->list.array[id];
|
||||
csi_period_offset(NULL,imcsi->periodicityAndOffset,&period,&offset);
|
||||
if((frame*nr_slots_per_frame[mu]+slot-offset)%period != 0)
|
||||
continue;
|
||||
fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csiim_config_pdu.csiim_config_rel15;
|
||||
const NR_BWP_Downlink_t *dlbwp = mac->DLbwp[dl_bwp_id-1];
|
||||
const int locationAndBandwidth = dlbwp != NULL ? dlbwp->bwp_Common->genericParameters.locationAndBandwidth:
|
||||
mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth;
|
||||
csiim_config_pdu->bwp_size = NRRIV2BW(locationAndBandwidth, MAX_BWP_SIZE);
|
||||
csiim_config_pdu->bwp_start = NRRIV2PRBOFFSET(locationAndBandwidth, MAX_BWP_SIZE);
|
||||
csiim_config_pdu->subcarrier_spacing = mu;
|
||||
csiim_config_pdu->start_rb = imcsi->freqBand->startingRB;
|
||||
csiim_config_pdu->nr_of_rbs = imcsi->freqBand->nrofRBs;
|
||||
// As specified in 5.2.2.4 of 38.214
|
||||
switch (imcsi->csi_IM_ResourceElementPattern->present) {
|
||||
case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern0:
|
||||
for (int i = 0; i<4; i++) {
|
||||
csiim_config_pdu->k_csiim[i] = (imcsi->csi_IM_ResourceElementPattern->choice.pattern0->subcarrierLocation_p0<<1) + (i>>1);
|
||||
csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern0->symbolLocation_p0 + (i%2);
|
||||
}
|
||||
break;
|
||||
case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1:
|
||||
for (int i = 0; i<4; i++) {
|
||||
csiim_config_pdu->k_csiim[i] = (imcsi->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1<<2) + i;
|
||||
csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid CSI-IM pattern\n");
|
||||
}
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_IM;
|
||||
dl_config->number_pdus = dl_config->number_pdus + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) {
|
||||
|
||||
if (mac->ra.ra_state != RA_SUCCEEDED && get_softmodem_params()->phy_test == 0)
|
||||
return;
|
||||
|
||||
NR_CellGroupConfig_t *CellGroup = mac->cg;
|
||||
|
||||
if (!CellGroup || !CellGroup->spCellConfig || !CellGroup->spCellConfig->spCellConfigDedicated ||
|
||||
!CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig)
|
||||
return;
|
||||
|
||||
NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
|
||||
|
||||
if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList == NULL)
|
||||
return;
|
||||
|
||||
fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
|
||||
NR_NZP_CSI_RS_Resource_t *nzpcsi;
|
||||
int period, offset;
|
||||
NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id;
|
||||
int mu = mac->DLbwp[dl_bwp_id-1] ?
|
||||
mac->DLbwp[dl_bwp_id-1]->bwp_Common->genericParameters.subcarrierSpacing :
|
||||
mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing;
|
||||
|
||||
for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){
|
||||
nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
|
||||
csi_period_offset(NULL,nzpcsi->periodicityAndOffset,&period,&offset);
|
||||
if((frame*nr_slots_per_frame[mu]+slot-offset)%period != 0)
|
||||
continue;
|
||||
LOG_D(MAC,"Scheduling reception of CSI-RS in frame %d slot %d\n",frame,slot);
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csirs_config_pdu.csirs_config_rel15;
|
||||
|
||||
NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping;
|
||||
|
||||
const NR_BWP_Downlink_t *dlbwp = mac->DLbwp[dl_bwp_id-1];
|
||||
const int locationAndBandwidth = dlbwp != NULL ? dlbwp->bwp_Common->genericParameters.locationAndBandwidth:
|
||||
mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth;
|
||||
csirs_config_pdu->bwp_size = NRRIV2BW(locationAndBandwidth, MAX_BWP_SIZE);
|
||||
csirs_config_pdu->bwp_start = NRRIV2PRBOFFSET(locationAndBandwidth, MAX_BWP_SIZE);
|
||||
csirs_config_pdu->subcarrier_spacing = mu;
|
||||
csirs_config_pdu->start_rb = resourceMapping.freqBand.startingRB;
|
||||
csirs_config_pdu->nr_of_rbs = resourceMapping.freqBand.nrofRBs;
|
||||
csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
|
||||
csirs_config_pdu->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain;
|
||||
if (resourceMapping.firstOFDMSymbolInTimeDomain2)
|
||||
csirs_config_pdu->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2;
|
||||
csirs_config_pdu->cdm_type = resourceMapping.cdm_Type;
|
||||
csirs_config_pdu->freq_density = resourceMapping.density.present;
|
||||
if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5)
|
||||
&& (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs))
|
||||
csirs_config_pdu->freq_density--;
|
||||
csirs_config_pdu->scramb_id = nzpcsi->scramblingID;
|
||||
switch(resourceMapping.frequencyDomainAllocation.present){
|
||||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1:
|
||||
csirs_config_pdu->row = 1;
|
||||
csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0])>>4)&0x0f;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2:
|
||||
csirs_config_pdu->row = 2;
|
||||
csirs_config_pdu->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) |
|
||||
((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<4)&0xff0));
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4:
|
||||
csirs_config_pdu->row = 4;
|
||||
csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0])>>5)&0x07;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other:
|
||||
csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0])>>2)&0x3f;
|
||||
// determining the row of table 7.4.1.5.3-1 in 38.211
|
||||
switch(resourceMapping.nrofPorts){
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p1:
|
||||
AssertFatal(1==0,"Resource with 1 CSI port shouldn't be within other rows\n");
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p2:
|
||||
csirs_config_pdu->row = 3;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p4:
|
||||
csirs_config_pdu->row = 5;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p8:
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||||
csirs_config_pdu->row = 8;
|
||||
else{
|
||||
int num_k = 0;
|
||||
for (int k=0; k<6; k++)
|
||||
num_k+=(((csirs_config_pdu->freq_domain)>>k)&0x01);
|
||||
if(num_k==4)
|
||||
csirs_config_pdu->row = 6;
|
||||
else
|
||||
csirs_config_pdu->row = 7;
|
||||
}
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p12:
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||||
csirs_config_pdu->row = 10;
|
||||
else
|
||||
csirs_config_pdu->row = 9;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p16:
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||||
csirs_config_pdu->row = 12;
|
||||
else
|
||||
csirs_config_pdu->row = 11;
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p24:
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||||
csirs_config_pdu->row = 14;
|
||||
else{
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
|
||||
csirs_config_pdu->row = 15;
|
||||
else
|
||||
csirs_config_pdu->row = 13;
|
||||
}
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p32:
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||||
csirs_config_pdu->row = 17;
|
||||
else{
|
||||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
|
||||
csirs_config_pdu->row = 18;
|
||||
else
|
||||
csirs_config_pdu->row = 16;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid number of ports in CSI-RS resource\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid freqency domain allocation in CSI-RS resource\n");
|
||||
}
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_RS;
|
||||
dl_config->number_pdus = dl_config->number_pdus + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
|
||||
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
|
||||
// - todo:
|
||||
|
||||
@@ -58,19 +58,42 @@ void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *
|
||||
struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_bearer2release_list,
|
||||
NR_UE_sched_ctrl_t *sched_ctrl) {
|
||||
|
||||
|
||||
if (rlc_bearer2add_list)
|
||||
// keep lcids
|
||||
for (int i=0;i<rlc_bearer2add_list->list.count;i++) {
|
||||
sched_ctrl->lcid_mask |= (1<<rlc_bearer2add_list->list.array[i]->logicalChannelIdentity);
|
||||
LOG_I(NR_MAC,"Adding LCID %d (%s %d)\n",
|
||||
(int)rlc_bearer2add_list->list.array[i]->logicalChannelIdentity,
|
||||
rlc_bearer2add_list->list.array[i]->logicalChannelIdentity<4 ? "SRB" : "DRB",
|
||||
(int)rlc_bearer2add_list->list.array[i]->logicalChannelIdentity);
|
||||
if (rlc_bearer2release_list) {
|
||||
for (int i = 0; i < rlc_bearer2release_list->list.count; i++) {
|
||||
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
|
||||
if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) {
|
||||
const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1;
|
||||
memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs);
|
||||
sched_ctrl->dl_lc_num--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rlc_bearer2release_list)
|
||||
for (int i=0;i<rlc_bearer2release_list->list.count;i++)
|
||||
sched_ctrl->lcid_mask |= (1<<*rlc_bearer2release_list->list.array[i]);
|
||||
}
|
||||
|
||||
if (rlc_bearer2add_list) {
|
||||
// keep lcids
|
||||
for (int i = 0; i < rlc_bearer2add_list->list.count; i++) {
|
||||
const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
|
||||
bool found = false;
|
||||
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
|
||||
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
sched_ctrl->dl_lc_num++;
|
||||
sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
|
||||
LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s: total num of active bearers %d) \n",
|
||||
__FUNCTION__,
|
||||
sched_ctrl->dl_lc_num);
|
||||
|
||||
}
|
||||
|
||||
@@ -629,17 +652,13 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
process_CellGroup(CellGroup,&UE_info->UE_sched_ctrl[UE_id]);
|
||||
const NR_ServingCellConfig_t *servingCellConfig = CellGroup ? CellGroup->spCellConfig->spCellConfigDedicated : NULL;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
sched_ctrl->update_pdsch_ps = true;
|
||||
sched_ctrl->update_pusch_ps = true;
|
||||
const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig ? servingCellConfig->pdsch_ServingCellConfig->choice.setup : NULL;
|
||||
if (sched_ctrl->available_dl_harq.len == 0) {
|
||||
if (get_softmodem_params()->sa) {
|
||||
// add all available DL HARQ processes for this UE in SA
|
||||
create_dl_harq_list(sched_ctrl, pdsch);
|
||||
}
|
||||
else {
|
||||
const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ?
|
||||
get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8;
|
||||
AssertFatal(sched_ctrl->available_dl_harq.len==nrofHARQ,
|
||||
"Reconfiguration of available harq processes not yet supported\n");
|
||||
}
|
||||
// update coreset/searchspace
|
||||
void *bwpd = NULL;
|
||||
NR_BWP_t *genericParameters = NULL;
|
||||
|
||||
@@ -318,7 +318,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const int last_slot = (slot + num_slots - 1) % num_slots;
|
||||
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL;
|
||||
memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
memcpy(&vrb_map_UL[last_slot * MAX_BWP_SIZE], &RC.nrmac[module_idP]->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
|
||||
clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
|
||||
|
||||
|
||||
@@ -389,7 +389,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
const int16_t N_RA_RB = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
uint16_t *vrb_map_UL = &cc->vrb_map_UL[slotP * MAX_BWP_SIZE];
|
||||
for (int i = 0; i < N_RA_RB * fdm; ++i)
|
||||
vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] = 0xff; // all symbols
|
||||
vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] = SL_to_bitmap(start_symbol, N_t_slot*N_dur);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -772,6 +772,8 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
int scs = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
|
||||
int fh = 0;
|
||||
int startSymbolAndLength = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
|
||||
int StartSymbolIndex, NrOfSymbols;
|
||||
SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
|
||||
int mappingtype = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType;
|
||||
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
|
||||
@@ -780,7 +782,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
int BWPSize = nr_mac->type0_PDCCH_CSS_config[ra->beam_id].num_rbs;
|
||||
int rbStart = 0;
|
||||
for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (BWPSize - ra->msg3_nb_rb)); i++) {
|
||||
if (vrb_map_UL[rbStart + BWPStart + i]) {
|
||||
if (vrb_map_UL[rbStart + BWPStart + i]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols)) {
|
||||
rbStart += i;
|
||||
i = 0;
|
||||
}
|
||||
@@ -898,7 +900,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
aggregation_level);
|
||||
|
||||
for (int rb = 0; rb < ra->msg3_nb_rb; rb++) {
|
||||
vrb_map_UL[rbStart + BWPStart + rb] = 1;
|
||||
vrb_map_UL[rbStart + BWPStart + rb] |= SL_to_bitmap(StartSymbolIndex, NrOfSymbols);
|
||||
}
|
||||
|
||||
// reset state to wait msg3
|
||||
@@ -928,6 +930,9 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
int mu = ubwp ?
|
||||
ubwp->bwp_Common->genericParameters.subcarrierSpacing :
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
|
||||
int StartSymbolIndex = 0;
|
||||
int NrOfSymbols = 0;
|
||||
int startSymbolAndLength = 0;
|
||||
int temp_slot = 0;
|
||||
ra->Msg3_tda_id = 16; // initialization to a value above limit
|
||||
|
||||
@@ -942,6 +947,8 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
int nb_slots_per_period = ((1<<mu)*10)/nb_periods_per_frame;
|
||||
for (int i=0; i<pusch_TimeDomainAllocationList->list.count; i++) {
|
||||
startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength;
|
||||
SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
|
||||
k2 = *pusch_TimeDomainAllocationList->list.array[i]->k2;
|
||||
// we want to transmit in the uplink symbols of mixed slot
|
||||
if ((k2 + DELTA[mu])%nb_slots_per_period == 0) {
|
||||
@@ -949,6 +956,8 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu];
|
||||
if (is_xlsch_in_slot(RC.nrmac[module_id]->ulsch_slot_bitmap[ra->Msg3_slot / 64], ra->Msg3_slot)) {
|
||||
ra->Msg3_tda_id = i;
|
||||
ra->msg3_startsymb = StartSymbolIndex;
|
||||
ra->msg3_nrsymb = NrOfSymbols;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1002,11 +1011,12 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
while (rbSize < msg3_nb_rb) {
|
||||
rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
|
||||
rbSize = 0;
|
||||
while (rbStart < bwpSize && vrb_map_UL[rbStart + bwpStart])
|
||||
while (rbStart < bwpSize &&
|
||||
(vrb_map_UL[rbStart + bwpStart]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols)))
|
||||
rbStart++;
|
||||
AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n");
|
||||
while (rbStart + rbSize < bwpSize
|
||||
&& !vrb_map_UL[rbStart + bwpStart + rbSize]
|
||||
&& !(vrb_map_UL[rbStart + bwpStart + rbSize]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols))
|
||||
&& rbSize < msg3_nb_rb)
|
||||
rbSize++;
|
||||
}
|
||||
@@ -1029,6 +1039,7 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
int start_symbol_index,nr_of_symbols;
|
||||
|
||||
SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols);
|
||||
int mcsindex = -1; // init value
|
||||
|
||||
pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
|
||||
pusch_pdu->rnti = rnti;
|
||||
@@ -1037,10 +1048,7 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
pusch_pdu->bwp_size = bwp_size;
|
||||
pusch_pdu->subcarrier_spacing = scs;
|
||||
pusch_pdu->cyclic_prefix = 0;
|
||||
pusch_pdu->mcs_index = 1;
|
||||
pusch_pdu->mcs_table = 0;
|
||||
pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table);
|
||||
pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table);
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL)
|
||||
pusch_pdu->transform_precoding = 1;
|
||||
else
|
||||
@@ -1077,15 +1085,23 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++)
|
||||
num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1;
|
||||
|
||||
pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->target_code_rate,
|
||||
pusch_pdu->rb_size,
|
||||
pusch_pdu->nr_of_symbols,
|
||||
num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol
|
||||
0, //nb_rb_oh
|
||||
0, // to verify tb scaling
|
||||
pusch_pdu->nrOfLayers)>>3;
|
||||
int TBS = 0;
|
||||
while(TBS<7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented)
|
||||
mcsindex++;
|
||||
pusch_pdu->target_code_rate = nr_get_code_rate_ul(mcsindex,pusch_pdu->mcs_table);
|
||||
pusch_pdu->qam_mod_order = nr_get_Qm_ul(mcsindex,pusch_pdu->mcs_table);
|
||||
TBS = nr_compute_tbs(pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->target_code_rate,
|
||||
pusch_pdu->rb_size,
|
||||
pusch_pdu->nr_of_symbols,
|
||||
num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol
|
||||
0, //nb_rb_oh
|
||||
0, // to verify tb scaling
|
||||
pusch_pdu->nrOfLayers)>>3;
|
||||
|
||||
pusch_pdu->mcs_index = mcsindex;
|
||||
pusch_pdu->pusch_data.tb_size = TBS;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu)
|
||||
@@ -1107,7 +1123,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
i + ra->msg3_first_rb,
|
||||
ra->Msg3_frame,
|
||||
ra->Msg3_slot);
|
||||
vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] = 1;
|
||||
vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] |= SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nrsymb);
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
|
||||
@@ -1179,7 +1195,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
time_domain_assignment = 1;
|
||||
else
|
||||
time_domain_assignment = 0;
|
||||
uint8_t mcsIndex = 0;
|
||||
int mcsIndex = -1; // initialization value
|
||||
int rbStart = 0;
|
||||
int rbSize = 8;
|
||||
|
||||
@@ -1336,9 +1352,6 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
pdsch_pdu_rel15->SubcarrierSpacing = genericParameters->subcarrierSpacing;
|
||||
pdsch_pdu_rel15->CyclicPrefix = 0;
|
||||
pdsch_pdu_rel15->NrOfCodewords = 1;
|
||||
pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,mcsTableIdx);
|
||||
pdsch_pdu_rel15->qamModOrder[0] = 2;
|
||||
pdsch_pdu_rel15->mcsIndex[0] = mcsIndex;
|
||||
pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx;
|
||||
pdsch_pdu_rel15->rvIndex[0] = 0;
|
||||
pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
|
||||
@@ -1362,9 +1375,38 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
startSymbolIndex,
|
||||
mappingtype, 1);
|
||||
|
||||
int x_Overhead = 0;
|
||||
uint8_t tb_scaling = 0;
|
||||
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, tb_scaling);
|
||||
int R, Qm;
|
||||
uint8_t N_PRB_DMRS;
|
||||
uint32_t TBS=0;
|
||||
if (dmrsConfigType == NFAPI_NR_DMRS_TYPE1) {
|
||||
// if no data in dmrs cdm group is 1 only even REs have no data
|
||||
// if no data in dmrs cdm group is 2 both odd and even REs have no data
|
||||
N_PRB_DMRS = pdsch_pdu_rel15->numDmrsCdmGrpsNoData*6;
|
||||
}
|
||||
else {
|
||||
N_PRB_DMRS = pdsch_pdu_rel15->numDmrsCdmGrpsNoData*4;
|
||||
}
|
||||
uint16_t dmrs_length = get_num_dmrs(pdsch_pdu_rel15->dlDmrsSymbPos);
|
||||
|
||||
while(TBS<9) { // min TBS for RAR is 9 bytes
|
||||
mcsIndex++;
|
||||
R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx);
|
||||
Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx);
|
||||
TBS = nr_compute_tbs(Qm,
|
||||
R,
|
||||
rbSize,
|
||||
nrOfSymbols,
|
||||
N_PRB_DMRS*dmrs_length,
|
||||
0, // overhead
|
||||
tb_scaling, // tb scaling
|
||||
1)>>3; // layers
|
||||
|
||||
pdsch_pdu_rel15->targetCodeRate[0] = R;
|
||||
pdsch_pdu_rel15->qamModOrder[0] = Qm;
|
||||
pdsch_pdu_rel15->mcsIndex[0] = mcsIndex;
|
||||
pdsch_pdu_rel15->TBSize[0] = TBS;
|
||||
}
|
||||
|
||||
// Fill PDCCH DL DCI PDU
|
||||
nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
|
||||
@@ -1651,12 +1693,15 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
uint8_t tb_scaling = 0;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map;
|
||||
do {
|
||||
rbSize++;
|
||||
if(rbSize < BWPSize)
|
||||
rbSize++;
|
||||
else
|
||||
mcsIndex++;
|
||||
LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",N_PRB_DMRS,N_DMRS_SLOT);
|
||||
harq->tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx),
|
||||
nr_get_code_rate_dl(mcsIndex, mcsTableIdx),
|
||||
rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3;
|
||||
} while (rbSize < BWPSize && harq->tb_size < ra->mac_pdu_length);
|
||||
nr_get_code_rate_dl(mcsIndex, mcsTableIdx),
|
||||
rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3;
|
||||
} while (harq->tb_size < ra->mac_pdu_length && mcsIndex<=28);
|
||||
|
||||
int i = 0;
|
||||
while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) {
|
||||
|
||||
@@ -612,14 +612,15 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
|
||||
int startSymbolIndex = 0;
|
||||
int nrOfSymbols = 0;
|
||||
bool is_typeA;
|
||||
|
||||
get_info_from_tda_tables(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern,
|
||||
time_domain_allocation,
|
||||
gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position,
|
||||
1, &startSymbolIndex, &nrOfSymbols);
|
||||
1, &is_typeA,
|
||||
&startSymbolIndex, &nrOfSymbols);
|
||||
|
||||
// TODO: There are exceptions to this in table 5.1.2.1.1-4,5 (Default time domain allocation tables B, C)
|
||||
int mappingtype = (startSymbolIndex <= 3)? typeA: typeB;
|
||||
int mappingtype = is_typeA? typeA: typeB;
|
||||
uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex, mappingtype, 1);
|
||||
|
||||
// Configure sched_ctrlCommon for SIB1
|
||||
@@ -639,7 +640,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
|
||||
|
||||
// Data to be transmitted
|
||||
bzero(tx_req->TLVs[0].value.direct,MAX_NR_DLSCH_PAYLOAD_BYTES);
|
||||
bzero(tx_req->TLVs[0].value.direct,MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*1056);
|
||||
memcpy(tx_req->TLVs[0].value.direct, sib1_payload, sib1_sdu_length);
|
||||
|
||||
tx_req->PDU_length = TBS;
|
||||
|
||||
@@ -393,12 +393,17 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
|
||||
#define BLER_UPDATE_FRAME 10
|
||||
#define BLER_FILTER 0.9f
|
||||
int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id)
|
||||
int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id, int mcs_table)
|
||||
{
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
|
||||
int max_allowed_mcs = (mcs_table == 1) ? 27 : 28;
|
||||
int max_mcs = nrmac->dl_max_mcs;
|
||||
if (nrmac->dl_max_mcs>max_allowed_mcs)
|
||||
max_mcs = max_allowed_mcs;
|
||||
|
||||
NR_DL_bler_stats_t *bler_stats = &nrmac->UE_info.UE_sched_ctrl[UE_id].dl_bler_stats;
|
||||
/* first call: everything is zero. Initialize to sensible default */
|
||||
if (bler_stats->last_frame_slot == 0 && bler_stats->mcs == 0) {
|
||||
@@ -444,7 +449,7 @@ int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t
|
||||
if (bler_stats->rd2_bler > nrmac->dl_rd2_bler_threshold && old_mcs > 6) {
|
||||
new_mcs -= 2;
|
||||
} else if (bler_stats->rd2_bler < nrmac->dl_rd2_bler_threshold) {*/
|
||||
if (bler_stats->bler < nrmac->dl_bler_target_lower && old_mcs < nrmac->dl_max_mcs && dtx > 9)
|
||||
if (bler_stats->bler < nrmac->dl_bler_target_lower && old_mcs < max_mcs && dtx > 9)
|
||||
new_mcs += 1;
|
||||
else if (bler_stats->bler > nrmac->dl_bler_target_upper && old_mcs > 6)
|
||||
new_mcs -= 1;
|
||||
@@ -466,76 +471,49 @@ void nr_store_dlsch_buffer(module_id_t module_id,
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->dl_pdus_total = 0;
|
||||
|
||||
int lcid;
|
||||
const uint16_t rnti = UE_info->rnti[UE_id];
|
||||
LOG_D(NR_MAC,"UE %d/%x : lcid_mask %x\n",UE_id,rnti,sched_ctrl->lcid_mask);
|
||||
if ((sched_ctrl->lcid_mask&(1<<2)) > 0)
|
||||
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1] = mac_rlc_status_ind(module_id,
|
||||
/* loop over all activated logical channels */
|
||||
// Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH
|
||||
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
const uint16_t rnti = UE_info->rnti[UE_id];
|
||||
LOG_D(NR_MAC, "In %s: UE %d/%x: LCID %d\n", __FUNCTION__, UE_id, rnti, lcid);
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
DL_SCH_LCID_DCCH1,
|
||||
lcid,
|
||||
0,
|
||||
0);
|
||||
if ((sched_ctrl->lcid_mask&(1<<1)) > 0)
|
||||
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH] = mac_rlc_status_ind(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
DL_SCH_LCID_DCCH,
|
||||
0,
|
||||
0);
|
||||
if ((sched_ctrl->lcid_mask&(1<<4)) > 0) {
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
sched_ctrl->rlc_status[DL_SCH_LCID_DTCH] = mac_rlc_status_ind(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
DL_SCH_LCID_DTCH,
|
||||
0,
|
||||
0);
|
||||
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
}
|
||||
if(sched_ctrl->rlc_status[DL_SCH_LCID_DCCH].bytes_in_buffer > 0){
|
||||
lcid = DL_SCH_LCID_DCCH;
|
||||
}
|
||||
else if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1].bytes_in_buffer > 0)
|
||||
{
|
||||
lcid = DL_SCH_LCID_DCCH1;
|
||||
}else{
|
||||
lcid = DL_SCH_LCID_DTCH;
|
||||
}
|
||||
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
//later multiplex here. Just select DCCH/SRB before DTCH/DRB
|
||||
sched_ctrl->lcid_to_schedule = lcid;
|
||||
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
|
||||
if (sched_ctrl->num_total_bytes == 0
|
||||
&& !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
|
||||
continue;
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"[%s][%d.%d], %s%d->DLSCH, RLC status %d bytes TA %d\n",
|
||||
__func__,
|
||||
frame,
|
||||
slot,
|
||||
lcid<4?"DCCH":"DTCH",
|
||||
lcid,
|
||||
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
||||
sched_ctrl->ta_apply);
|
||||
sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
LOG_D(MAC,
|
||||
"[gNB %d][%4d.%2d] %s%d->DLSCH, RLC status for UE %d: %d bytes in buffer, total DL buffer size = %d bytes, %d total PDU bytes, %s TA command\n",
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
lcid < 4 ? "DCCH":"DTCH",
|
||||
lcid,
|
||||
UE_id,
|
||||
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
||||
sched_ctrl->num_total_bytes,
|
||||
sched_ctrl->dl_pdus_total,
|
||||
sched_ctrl->ta_apply ? "send":"do not send");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,8 +564,10 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
}
|
||||
/* check whether we need to switch the TDA allocation since the last
|
||||
* (re-)transmission */
|
||||
if (ps->time_domain_allocation != tda)
|
||||
nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, bwpd, tda, ps->nrOfLayers, sched_ctrl, ps);
|
||||
if (ps->time_domain_allocation != tda || sched_ctrl->update_pdsch_ps) {
|
||||
nr_set_pdsch_semi_static(scc, cg, sched_ctrl->active_bwp, bwpd, tda, ps->nrOfLayers, sched_ctrl, ps);
|
||||
sched_ctrl->update_pdsch_ps = false;
|
||||
}
|
||||
} else {
|
||||
/* the retransmission will use a different time domain allocation, check
|
||||
* that we have enough resources */
|
||||
@@ -684,7 +664,7 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
/* retransmissions: directly allocate */
|
||||
*n_rb_sched -= sched_ctrl->sched_pdsch.rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pdsch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pdsch.rbStart] -= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
rballoc_mask[rb + sched_ctrl->sched_pdsch.rbStart] ^= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -744,7 +724,7 @@ void pf_dl(module_id_t module_id,
|
||||
|
||||
/* Calculate coeff */
|
||||
set_dl_mcs(sched_pdsch,sched_ctrl,&mac->dl_max_mcs,ps->mcsTableIdx);
|
||||
sched_pdsch->mcs = get_mcs_from_bler(module_id, /* CC_id = */ 0, frame, slot, UE_id);
|
||||
sched_pdsch->mcs = get_mcs_from_bler(module_id, /* CC_id = */ 0, frame, slot, UE_id, ps->mcsTableIdx);
|
||||
layers[UE_id] = set_dl_nrOfLayers(sched_ctrl);
|
||||
const uint8_t Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx);
|
||||
const uint16_t R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx);
|
||||
@@ -855,6 +835,10 @@ void pf_dl(module_id_t module_id,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
if (max_num_ue < 0) return;
|
||||
|
||||
/* MCS has been set above */
|
||||
|
||||
const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot];
|
||||
@@ -863,8 +847,11 @@ void pf_dl(module_id_t module_id,
|
||||
NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
|
||||
|
||||
if (ps->nrOfLayers != layers[UE_id] ||
|
||||
ps->time_domain_allocation != tda)
|
||||
ps->time_domain_allocation != tda ||
|
||||
sched_ctrl->update_pdsch_ps) {
|
||||
nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, bwpd, tda, layers[UE_id], sched_ctrl, ps);
|
||||
sched_ctrl->update_pdsch_ps = false;
|
||||
}
|
||||
|
||||
const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
// Freq-demain allocation
|
||||
@@ -882,7 +869,12 @@ void pf_dl(module_id_t module_id,
|
||||
sched_pdsch->pucch_allocation = alloc;
|
||||
uint32_t TBS = 0;
|
||||
uint16_t rbSize;
|
||||
const int oh = 3 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
|
||||
// Fix me: currently, the RLC does not give us the total number of PDUs
|
||||
// awaiting. Therefore, for the time being, we put a fixed overhead of 12
|
||||
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
|
||||
// PDUs, we replace with 3 * numPDUs
|
||||
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
|
||||
//const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
|
||||
nr_find_nb_rb(sched_pdsch->Qm,
|
||||
sched_pdsch->R,
|
||||
ps->nrOfLayers,
|
||||
@@ -900,7 +892,7 @@ void pf_dl(module_id_t module_id,
|
||||
/* transmissions: directly allocate */
|
||||
n_rb_sched -= sched_pdsch->rbSize;
|
||||
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
|
||||
rballoc_mask[rb + sched_pdsch->rbStart] -= slbitmap;
|
||||
rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1339,68 +1331,72 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
buf += written;
|
||||
int size = TBS - written;
|
||||
DevAssert(size >= 0);
|
||||
|
||||
/* next, get RLC data */
|
||||
|
||||
// const int lcid = DL_SCH_LCID_DTCH;
|
||||
const int lcid = sched_ctrl->lcid_to_schedule;
|
||||
int dlsch_total_bytes = 0;
|
||||
start_meas(&gNB_mac->rlc_data_req);
|
||||
if (sched_ctrl->num_total_bytes > 0) {
|
||||
tbs_size_t len = 0;
|
||||
while (size > 3) {
|
||||
// we do not know how much data we will get from RLC, i.e., whether it
|
||||
// will be longer than 256B or not. Therefore, reserve space for long header, then
|
||||
// fetch data, then fill real length
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
buf += 3;
|
||||
size -= 3;
|
||||
|
||||
/* limit requested number of bytes to what preprocessor specified, or
|
||||
* such that TBS is full */
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
|
||||
/* loop over all activated logical channels */
|
||||
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||
|
||||
len = mac_rlc_data_req(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
ndata,
|
||||
(char *)buf,
|
||||
0,
|
||||
0);
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue; // no data for this LC
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n",
|
||||
frame,
|
||||
slot,
|
||||
rnti,
|
||||
len,
|
||||
lcid < 4 ? "DCCH" : "DTCH",
|
||||
lcid,
|
||||
ndata,
|
||||
size);
|
||||
if (len == 0)
|
||||
break;
|
||||
int dlsch_total_bytes = 0;
|
||||
while (size > 3) {
|
||||
// we do not know how much data we will get from RLC, i.e., whether it
|
||||
// will be longer than 256B or not. Therefore, reserve space for long header, then
|
||||
// fetch data, then fill real length
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
buf += 3;
|
||||
size -= 3;
|
||||
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
header->L1 = (len >> 8) & 0xff;
|
||||
header->L2 = len & 0xff;
|
||||
size -= len;
|
||||
buf += len;
|
||||
dlsch_total_bytes += len;
|
||||
/* limit requested number of bytes to what preprocessor specified, or
|
||||
* such that TBS is full */
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
|
||||
tbs_size_t len = mac_rlc_data_req(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
ndata,
|
||||
(char *)buf,
|
||||
0,
|
||||
0);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n",
|
||||
frame,
|
||||
slot,
|
||||
rnti,
|
||||
len,
|
||||
lcid < 4 ? "DCCH" : "DTCH",
|
||||
lcid,
|
||||
ndata,
|
||||
size);
|
||||
if (len == 0) {
|
||||
/* RLC did not have data anymore, mark buffer as unused */
|
||||
buf -= 3;
|
||||
size += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
header->L1 = (len >> 8) & 0xff;
|
||||
header->L2 = len & 0xff;
|
||||
size -= len;
|
||||
buf += len;
|
||||
dlsch_total_bytes += len;
|
||||
}
|
||||
|
||||
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
|
||||
}
|
||||
if (len == 0) {
|
||||
/* RLC did not have data anymore, mark buffer as unused */
|
||||
buf -= 3;
|
||||
size += 3;
|
||||
}
|
||||
}
|
||||
else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
|
||||
} else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
|
||||
/* we will need the large header, phy-test typically allocates all
|
||||
* resources and fills to the last byte below */
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
@@ -1418,7 +1414,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
header->L2 = size & 0xff;
|
||||
size -= size;
|
||||
buf += size;
|
||||
dlsch_total_bytes += size;
|
||||
}
|
||||
stop_meas(&gNB_mac->rlc_data_req);
|
||||
|
||||
@@ -1438,7 +1433,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
|
||||
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
|
||||
UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
|
||||
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
|
||||
|
||||
/* save retransmission information */
|
||||
harq->sched_pdsch = *sched_pdsch;
|
||||
|
||||
@@ -55,8 +55,6 @@ extern RAN_CONTEXT_t RC;
|
||||
|
||||
//#define ENABLE_MAC_PAYLOAD_DEBUG 1
|
||||
|
||||
//uint8_t mac_pdu[MAX_NR_DLSCH_PAYLOAD_BYTES];
|
||||
|
||||
/*Scheduling of DLSCH with associated DCI in common search space
|
||||
* current version has only a DCI for type 1 PDCCH for C_RNTI*/
|
||||
void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
|
||||
@@ -314,7 +312,9 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
}
|
||||
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->dl_lc_num = 1;
|
||||
const int lcid = DL_SCH_LCID_DTCH;
|
||||
sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
|
||||
const uint16_t rnti = UE_info->rnti[UE_id];
|
||||
/* update sched_ctrl->num_total_bytes so that postprocessor schedules data,
|
||||
* if available */
|
||||
@@ -329,7 +329,6 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
0,
|
||||
0);
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
sched_ctrl->lcid_to_schedule = lcid;
|
||||
|
||||
uint8_t nr_of_candidates;
|
||||
for (int i=0; i<5; i++) {
|
||||
@@ -481,9 +480,8 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
|
||||
uint16_t *vrb_map_UL =
|
||||
&RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
|
||||
const uint16_t symb = ((1 << ps->nrOfSymbols) - 1) << ps->startSymbolIndex;
|
||||
for (int i = rbStart; i < rbStart + rbSize; ++i) {
|
||||
if ((vrb_map_UL[i+BWPStart] & symb) != 0) {
|
||||
if ((vrb_map_UL[i+BWPStart] & SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)) != 0) {
|
||||
LOG_E(MAC,
|
||||
"%s(): %4d.%2d RB %d is already reserved, cannot schedule UE\n",
|
||||
__func__,
|
||||
@@ -561,6 +559,6 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
sched_ctrl->aggregation_level);
|
||||
|
||||
for (int rb = rbStart; rb < rbStart + rbSize; rb++)
|
||||
vrb_map_UL[rb+BWPStart] = 1;
|
||||
vrb_map_UL[rb+BWPStart] |= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -557,6 +557,7 @@ void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc,
|
||||
ps->mcsTableIdx = 2;
|
||||
}
|
||||
else ps->mcsTableIdx = 0;
|
||||
LOG_D(NR_MAC,"MCS Table Index: %d\n",ps->mcsTableIdx);
|
||||
|
||||
NR_PDSCH_Config_t *pdsch_Config;
|
||||
if (bwp &&
|
||||
@@ -1259,23 +1260,26 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
else { // this is the default PUCCH configuration, PUCCH format 0 or 1
|
||||
LOG_D(NR_MAC,"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, bwp %p)\n",r_pucch,bwp);
|
||||
int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon;
|
||||
int prboffset = r_pucch/default_pucch_csset[rsetindex];
|
||||
int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex];
|
||||
pucch_pdu->prb_start = (r_pucch>>3)==0 ?
|
||||
default_pucch_prboffset[rsetindex] + prboffset:
|
||||
pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8;
|
||||
int prb_start, second_hop_prb, nr_of_symb, start_symb;
|
||||
set_r_pucch_parms(rsetindex,
|
||||
r_pucch,
|
||||
pucch_pdu->bwp_size,
|
||||
&prb_start,
|
||||
&second_hop_prb,
|
||||
&nr_of_symb,
|
||||
&start_symb);
|
||||
|
||||
pucch_pdu->prb_start = prb_start;
|
||||
pucch_pdu->rnti = rnti;
|
||||
pucch_pdu->freq_hop_flag = 1;
|
||||
pucch_pdu->second_hop_prb = (r_pucch>>3)==0?
|
||||
pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset:
|
||||
default_pucch_prboffset[rsetindex] + prboffsetm8;
|
||||
pucch_pdu->second_hop_prb = second_hop_prb;
|
||||
pucch_pdu->format_type = default_pucch_fmt[rsetindex];
|
||||
pucch_pdu->initial_cyclic_shift = r_pucch%default_pucch_csset[rsetindex];
|
||||
if (rsetindex==3||rsetindex==7||rsetindex==11) pucch_pdu->initial_cyclic_shift*=6;
|
||||
else if (rsetindex==1||rsetindex==2) pucch_pdu->initial_cyclic_shift*=3;
|
||||
else pucch_pdu->initial_cyclic_shift*=4;
|
||||
pucch_pdu->nr_of_symbols = default_pucch_numbsymb[rsetindex];
|
||||
pucch_pdu->start_symbol_index = default_pucch_firstsymb[rsetindex];
|
||||
pucch_pdu->nr_of_symbols = nr_of_symb;
|
||||
pucch_pdu->start_symbol_index = start_symb;
|
||||
if (pucch_pdu->format_type == 1) pucch_pdu->time_domain_occ_idx = 0; // check this!!
|
||||
pucch_pdu->sr_flag = O_sr;
|
||||
pucch_pdu->prb_size=1;
|
||||
@@ -1283,6 +1287,32 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
}
|
||||
|
||||
|
||||
void set_r_pucch_parms(int rsetindex,
|
||||
int r_pucch,
|
||||
int bwp_size,
|
||||
int *prb_start,
|
||||
int *second_hop_prb,
|
||||
int *nr_of_symbols,
|
||||
int *start_symbol_index) {
|
||||
|
||||
// procedure described in 38.213 section 9.2.1
|
||||
|
||||
int prboffset = r_pucch/default_pucch_csset[rsetindex];
|
||||
int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex];
|
||||
|
||||
*prb_start = (r_pucch>>3)==0 ?
|
||||
default_pucch_prboffset[rsetindex] + prboffset:
|
||||
bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8;
|
||||
|
||||
*second_hop_prb = (r_pucch>>3)==0?
|
||||
bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset:
|
||||
default_pucch_prboffset[rsetindex] + prboffsetm8;
|
||||
|
||||
*nr_of_symbols = default_pucch_numbsymb[rsetindex];
|
||||
*start_symbol_index = default_pucch_firstsymb[rsetindex];
|
||||
}
|
||||
|
||||
|
||||
void prepare_dci(const NR_CellGroupConfig_t *CellGroup,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_dci_format_t format,
|
||||
@@ -1967,14 +1997,45 @@ void dump_nr_list(NR_list_t *listP)
|
||||
void create_nr_list(NR_list_t *list, int len)
|
||||
{
|
||||
list->head = -1;
|
||||
list->next = calloc(len, sizeof(*list->next));
|
||||
AssertFatal(list, "cannot calloc() memory for NR_list_t->next\n");
|
||||
list->next = malloc(len * sizeof(*list->next));
|
||||
AssertFatal(list->next, "cannot malloc() memory for NR_list_t->next\n");
|
||||
for (int i = 0; i < len; ++i)
|
||||
list->next[i] = -1;
|
||||
list->tail = -1;
|
||||
list->len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize an NR_list
|
||||
*/
|
||||
void resize_nr_list(NR_list_t *list, int new_len)
|
||||
{
|
||||
if (new_len == list->len)
|
||||
return;
|
||||
if (new_len > list->len) {
|
||||
/* list->head remains */
|
||||
const int old_len = list->len;
|
||||
int* n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
for (int i = old_len; i < new_len; ++i)
|
||||
list->next[i] = -1;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
} else { /* new_len < len */
|
||||
AssertFatal(list->head < new_len, "shortened list head out of index %d (new len %d)\n", list->head, new_len);
|
||||
AssertFatal(list->tail < new_len, "shortened list tail out of index %d (new len %d)\n", list->head, new_len);
|
||||
for (int i = 0; i < list->len; ++i)
|
||||
AssertFatal(list->next[i] < new_len, "shortened list entry out of index %d (new len %d)\n", list->next[i], new_len);
|
||||
/* list->head remains */
|
||||
int *n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an NR_list
|
||||
*/
|
||||
@@ -2174,10 +2235,6 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG
|
||||
memset(sched_ctrl, 0, sizeof(*sched_ctrl));
|
||||
sched_ctrl->set_mcs = true;
|
||||
sched_ctrl->set_pmi = false;
|
||||
sched_ctrl->lcid_mask = 0;
|
||||
if (!get_softmodem_params()->phy_test && !get_softmodem_params()->do_ra && !get_softmodem_params()->sa) {
|
||||
sched_ctrl->lcid_mask = 1<<DL_SCH_LCID_DTCH;
|
||||
}
|
||||
sched_ctrl->ta_frame = 0;
|
||||
sched_ctrl->ta_update = 31;
|
||||
sched_ctrl->ta_apply = false;
|
||||
@@ -2231,10 +2288,8 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG
|
||||
"no pdsch-ServingCellConfig found for UE %d\n",
|
||||
UE_id);
|
||||
const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig ? servingCellConfig->pdsch_ServingCellConfig->choice.setup : NULL;
|
||||
// add DL HARQ processes for this UE only in NSA
|
||||
// (SA still doesn't have information on nrofHARQ_ProcessesForPDSCH at this stage)
|
||||
if (!get_softmodem_params()->sa)
|
||||
create_dl_harq_list(sched_ctrl,pdsch);
|
||||
// pdsch == NULL in SA -> will create default (8) number of HARQ processes
|
||||
create_dl_harq_list(sched_ctrl, pdsch);
|
||||
// add all available UL HARQ processes for this UE
|
||||
// nb of ul harq processes not configurable
|
||||
create_nr_list(&sched_ctrl->available_ul_harq, 16);
|
||||
@@ -2262,11 +2317,31 @@ void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ?
|
||||
get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8;
|
||||
// add all available DL HARQ processes for this UE
|
||||
create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
|
||||
for (int harq = 0; harq < nrofHARQ; harq++)
|
||||
add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
|
||||
create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
|
||||
create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
|
||||
AssertFatal(sched_ctrl->available_dl_harq.len == sched_ctrl->feedback_dl_harq.len
|
||||
&& sched_ctrl->available_dl_harq.len == sched_ctrl->retrans_dl_harq.len,
|
||||
"HARQ lists have different lengths (%d/%d/%d)\n",
|
||||
sched_ctrl->available_dl_harq.len,
|
||||
sched_ctrl->feedback_dl_harq.len,
|
||||
sched_ctrl->retrans_dl_harq.len);
|
||||
if (sched_ctrl->available_dl_harq.len == 0) {
|
||||
create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
|
||||
for (int harq = 0; harq < nrofHARQ; harq++)
|
||||
add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
|
||||
create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
|
||||
create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
|
||||
} else if (sched_ctrl->available_dl_harq.len == nrofHARQ) {
|
||||
LOG_D(NR_MAC, "nrofHARQ %d already configured\n", nrofHARQ);
|
||||
} else {
|
||||
const int old_nrofHARQ = sched_ctrl->available_dl_harq.len;
|
||||
AssertFatal(nrofHARQ > old_nrofHARQ,
|
||||
"cannot resize HARQ list to be smaller (nrofHARQ %d, old_nrofHARQ %d)\n",
|
||||
nrofHARQ, old_nrofHARQ);
|
||||
resize_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
|
||||
for (int harq = old_nrofHARQ; harq < nrofHARQ; harq++)
|
||||
add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
|
||||
resize_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
|
||||
resize_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
|
||||
}
|
||||
}
|
||||
|
||||
/* hack data to remove UE in the phy */
|
||||
@@ -2475,11 +2550,11 @@ void nr_csirs_scheduling(int Mod_idP,
|
||||
for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){
|
||||
nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
|
||||
NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping;
|
||||
csi_period_offset(NULL,nzpcsi,&period,&offset);
|
||||
csi_period_offset(NULL,nzpcsi->periodicityAndOffset,&period,&offset);
|
||||
|
||||
if((frame*n_slots_frame+slot-offset)%period == 0) {
|
||||
|
||||
LOG_I(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot);
|
||||
LOG_D(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot);
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
@@ -2523,7 +2598,7 @@ void nr_csirs_scheduling(int Mod_idP,
|
||||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2:
|
||||
csirs_pdu_rel15->row = 2;
|
||||
csirs_pdu_rel15->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) |
|
||||
((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<8)&0xff0));
|
||||
((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<4)&0xff0));
|
||||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||||
break;
|
||||
@@ -2538,6 +2613,7 @@ void nr_csirs_scheduling(int Mod_idP,
|
||||
// determining the row of table 7.4.1.5.3-1 in 38.211
|
||||
switch(resourceMapping.nrofPorts){
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p1:
|
||||
AssertFatal(1==0,"Resource with 1 CSI port shouldn't be within other rows\n");
|
||||
break;
|
||||
case NR_CSI_RS_ResourceMapping__nrofPorts_p2:
|
||||
csirs_pdu_rel15->row = 3;
|
||||
|
||||
@@ -79,7 +79,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],
|
||||
@@ -761,16 +763,16 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
switch(pucchres->format.present){
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
len = pucchres->format.choice.format2->nrofPRBs;
|
||||
mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
len = pucchres->format.choice.format3->nrofPRBs;
|
||||
mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format3->startingSymbolIndex, pucchres->format.choice.format3->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format4->startingSymbolIndex, pucchres->format.choice.format4->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
default:
|
||||
@@ -778,7 +780,12 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
}
|
||||
// verify resources are free
|
||||
for (int i = start; i < start + len; ++i) {
|
||||
vrb_map_UL[i+bwp_start] |= mask;
|
||||
if((vrb_map_UL[i+bwp_start] & mask) != 0) {
|
||||
LOG_E(NR_MAC, "%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", frame, slot, frame, sched_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
else
|
||||
vrb_map_UL[i+bwp_start] |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1512,6 +1519,61 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
NR_sched_pucch_t *pucch,
|
||||
uint16_t *vrb_map_UL,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
int r_pucch,
|
||||
int bwp_start,
|
||||
int bwp_size) {
|
||||
|
||||
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap
|
||||
|
||||
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1];
|
||||
if (csi_pucch &&
|
||||
csi_pucch->csi_bits > 0 &&
|
||||
csi_pucch->frame == pucch->frame &&
|
||||
csi_pucch->ul_slot == pucch->ul_slot &&
|
||||
csi_pucch->simultaneous_harqcsi &&
|
||||
(csi_pucch->csi_bits + csi_pucch->dai_c) < 11)
|
||||
return true; // available resources for csi_pucch already verified
|
||||
|
||||
if(r_pucch<0){
|
||||
const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[0];
|
||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||
pucch->second_hop_prb = resource->secondHopPRB!= NULL ? *resource->secondHopPRB : 0;
|
||||
pucch->nr_of_symb = resource->format.choice.format0->nrofSymbols;
|
||||
pucch->start_symb = resource->format.choice.format0->startingSymbolIndex;
|
||||
pucch->prb_start = resource->startingPRB;
|
||||
}
|
||||
else{
|
||||
int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon;
|
||||
set_r_pucch_parms(rsetindex,
|
||||
r_pucch,
|
||||
bwp_size,
|
||||
&pucch->prb_start,
|
||||
&pucch->second_hop_prb,
|
||||
&pucch->nr_of_symb,
|
||||
&pucch->start_symb);
|
||||
}
|
||||
|
||||
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
|
||||
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
||||
int prb;
|
||||
if (l==1 && pucch->second_hop_prb != 0)
|
||||
prb = pucch->second_hop_prb;
|
||||
else
|
||||
prb = pucch->prb_start;
|
||||
if ((vrb_map_UL[bwp_start+prb] & symb) != 0) {
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// this function returns an index to NR_sched_pucch structure
|
||||
// currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1
|
||||
@@ -1551,6 +1613,24 @@ int nr_acknack_scheduling(int mod_id,
|
||||
* later)
|
||||
* * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
|
||||
NR_CellGroupConfig_t *cg = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id];
|
||||
|
||||
NR_PUCCH_Config_t *pucch_Config = NULL;
|
||||
if (sched_ctrl->active_ubwp) {
|
||||
pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
} else if (cg &&
|
||||
cg->spCellConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated &&
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) {
|
||||
pucch_Config = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
|
||||
}
|
||||
NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ?
|
||||
&sched_ctrl->active_ubwp->bwp_Common->genericParameters:
|
||||
&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||||
int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE);
|
||||
int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
|
||||
LOG_D(NR_MAC, "In %s: %d.%d Trying to allocate pucch, current DAI %d\n", __FUNCTION__, frame, slot, pucch->dai_c);
|
||||
|
||||
@@ -1596,7 +1676,6 @@ int nr_acknack_scheduling(int mod_id,
|
||||
LOG_D(NR_MAC, "In %s: pucch_acknak 1. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n", __FUNCTION__, frame, slot, pucch->frame, pucch->ul_slot, pucch->dai_c);
|
||||
|
||||
// this is hardcoded for now as ue specific only if we are not on the initialBWP (to be fixed to allow ue_Specific also on initialBWP
|
||||
NR_CellGroupConfig_t *cg = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id];
|
||||
NR_BWP_UplinkDedicated_t *ubwpd=NULL;
|
||||
|
||||
if (cg &&
|
||||
@@ -1670,23 +1749,36 @@ int nr_acknack_scheduling(int mod_id,
|
||||
// Find the right timing_indicator value.
|
||||
int ind_found = -1;
|
||||
// while we are within the feedback limits
|
||||
uint16_t *vrb_map_UL;
|
||||
while ((n_slots_frame + pucch->ul_slot - slot) % n_slots_frame <= max_fb_time) {
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
LOG_D(NR_MAC, "In %s: pdsch_to_harq_feedback[%d] = %d (pucch->ul_slot %d - slot %d)\n", __FUNCTION__,
|
||||
i,pdsch_to_harq_feedback[i],pucch->ul_slot,slot);
|
||||
int diff = pucch->ul_slot - slot;
|
||||
if (diff<0)
|
||||
diff += n_slots_frame;
|
||||
if (pdsch_to_harq_feedback[i] == diff &&
|
||||
pdsch_to_harq_feedback[i] >= minfbtime) {
|
||||
ind_found = i;
|
||||
break;
|
||||
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
|
||||
vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
||||
bool ret = test_acknack_vrb_occupation(sched_ctrl,
|
||||
pucch,
|
||||
vrb_map_UL,
|
||||
scc,
|
||||
pucch_Config,
|
||||
r_pucch,
|
||||
bwp_start,
|
||||
bwp_size);
|
||||
if (ret) {
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
LOG_D(NR_MAC,"pdsch_to_harq_feedback[%d] = %d (pucch->ul_slot %d - slot %d)\n",
|
||||
i,pdsch_to_harq_feedback[i],pucch->ul_slot,slot);
|
||||
int diff = pucch->ul_slot - slot;
|
||||
if (diff<0)
|
||||
diff += n_slots_frame;
|
||||
if (pdsch_to_harq_feedback[i] == diff &&
|
||||
pdsch_to_harq_feedback[i] >= minfbtime) {
|
||||
ind_found = i;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
++i;
|
||||
if (ind_found!=-1)
|
||||
break;
|
||||
}
|
||||
if (ind_found!=-1)
|
||||
break;
|
||||
// advance to the next ul slot
|
||||
const int f = pucch->frame;
|
||||
const int s = pucch->ul_slot;
|
||||
@@ -1747,46 +1839,16 @@ int nr_acknack_scheduling(int mod_id,
|
||||
pucch->dai_c++;
|
||||
pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
|
||||
pucch->r_pucch=r_pucch;
|
||||
NR_PUCCH_Config_t *pucch_Config = NULL;
|
||||
if (sched_ctrl->active_ubwp) {
|
||||
pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
} else if (RC.nrmac[mod_id]->UE_info.CellGroup[UE_id] &&
|
||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig &&
|
||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated &&
|
||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig &&
|
||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP &&
|
||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) {
|
||||
pucch_Config = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
|
||||
}
|
||||
|
||||
NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ?
|
||||
&sched_ctrl->active_ubwp->bwp_Common->genericParameters:
|
||||
&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||||
int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE);
|
||||
|
||||
/* verify that at that slot and symbol, resources are free. We only do this
|
||||
* for initialCyclicShift 0 (we assume it always has that one), so other
|
||||
* initialCyclicShifts can overlap with ICS 0!*/
|
||||
|
||||
if (pucch_Config) {
|
||||
const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[pucch->resource_indicator];
|
||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||
int second_hop_prb = resource->secondHopPRB!= NULL ? *resource->secondHopPRB : 0;
|
||||
int nr_of_symbols = resource->format.choice.format0->nrofSymbols;
|
||||
if (resource->format.choice.format0->initialCyclicShift == 0) {
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
||||
for (int l=0; l<nr_of_symbols; l++) {
|
||||
uint16_t symb = 1 << (resource->format.choice.format0->startingSymbolIndex + l);
|
||||
int prb;
|
||||
if (l==1 && second_hop_prb != 0)
|
||||
prb = second_hop_prb;
|
||||
else
|
||||
prb = resource->startingPRB;
|
||||
if ((vrb_map_UL[bwp_start+prb] & symb) != 0)
|
||||
LOG_W(MAC, "symbol 0x%x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d.%d\n", symb, resource->startingPRB, pucch->frame, pucch->ul_slot);
|
||||
vrb_map_UL[bwp_start+prb] |= symb;
|
||||
}
|
||||
}
|
||||
vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
||||
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
||||
int prb;
|
||||
if (l==1 && pucch->second_hop_prb != 0)
|
||||
prb = pucch->second_hop_prb;
|
||||
else
|
||||
prb = pucch->prb_start;
|
||||
vrb_map_UL[bwp_start+prb] |= symb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1886,12 +1948,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,6 +818,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
|
||||
UE_info->active[UE_id] = true;
|
||||
|
||||
process_CellGroup(ra->CellGroup, UE_scheduling_control);
|
||||
|
||||
} else {
|
||||
|
||||
LOG_A(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP);
|
||||
@@ -956,7 +958,7 @@ int next_list_entry_looped(NR_list_t *list, int UE_id)
|
||||
bool allocate_ul_retransmission(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
uint8_t *rballoc_mask,
|
||||
uint16_t *rballoc_mask,
|
||||
int *n_rb_sched,
|
||||
int UE_id,
|
||||
int harq_pid)
|
||||
@@ -977,13 +979,6 @@ bool allocate_ul_retransmission(module_id_t module_id,
|
||||
LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda);
|
||||
LOG_D(NR_MAC,"num_dmrs_cdm_grps_no_data %d, tbs %d\n",num_dmrs_cdm_grps_no_data, retInfo->tb_size);
|
||||
if (tda == retInfo->time_domain_allocation) {
|
||||
/* Check the resource is enough for retransmission */
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart])
|
||||
rbStart++;
|
||||
if (rbStart + retInfo->rbSize > bwpSize) {
|
||||
LOG_W(NR_MAC, "cannot allocate retransmission of UE %d/RNTI %04x: no resources (rbStart %d, retInfo->rbSize %d, bwpSize %d\n", UE_id, UE_info->rnti[UE_id], rbStart, retInfo->rbSize, bwpSize);
|
||||
return false;
|
||||
}
|
||||
/* check whether we need to switch the TDA allocation since tha last
|
||||
* (re-)transmission */
|
||||
NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
|
||||
@@ -992,20 +987,34 @@ bool allocate_ul_retransmission(module_id_t module_id,
|
||||
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data
|
||||
|| sched_ctrl->update_pusch_ps) {
|
||||
nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
|
||||
sched_ctrl->update_pusch_ps = false;
|
||||
}
|
||||
|
||||
/* Check the resource is enough for retransmission */
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)))
|
||||
rbStart++;
|
||||
if (rbStart + retInfo->rbSize > bwpSize) {
|
||||
LOG_W(NR_MAC, "cannot allocate retransmission of UE %d/RNTI %04x: no resources (rbStart %d, retInfo->rbSize %d, bwpSize %d\n", UE_id, UE_info->rnti[UE_id], rbStart, retInfo->rbSize, bwpSize);
|
||||
return false;
|
||||
}
|
||||
LOG_D(NR_MAC, "%s(): retransmission keeping TDA %d and TBS %d\n", __func__, tda, retInfo->tb_size);
|
||||
} else {
|
||||
/* the retransmission will use a different time domain allocation, check
|
||||
* that we have enough resources */
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart])
|
||||
rbStart++;
|
||||
int rbSize = 0;
|
||||
while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize])
|
||||
rbSize++;
|
||||
NR_pusch_semi_static_t temp_ps;
|
||||
int dci_format = get_dci_format(sched_ctrl);
|
||||
nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp,ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, &temp_ps);
|
||||
/* the retransmission will use a different time domain allocation, check
|
||||
* that we have enough resources */
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols)))
|
||||
rbStart++;
|
||||
int rbSize = 0;
|
||||
while (rbStart + rbSize < bwpSize &&
|
||||
(rballoc_mask[rbStart + rbSize]&SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols)))
|
||||
rbSize++;
|
||||
uint32_t new_tbs;
|
||||
uint16_t new_rbSize;
|
||||
bool success = nr_find_nb_rb(retInfo->Qm,
|
||||
@@ -1088,7 +1097,7 @@ bool allocate_ul_retransmission(module_id_t module_id,
|
||||
/* Mark the corresponding RBs as used */
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= SL_to_bitmap(sched_ctrl->pusch_semi_static.startSymbolIndex, sched_ctrl->pusch_semi_static.nrOfSymbols);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1112,7 +1121,7 @@ void pf_ul(module_id_t module_id,
|
||||
NR_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rb_sched,
|
||||
uint8_t *rballoc_mask) {
|
||||
uint16_t *rballoc_mask) {
|
||||
|
||||
const int CC_id = 0;
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
|
||||
@@ -1206,8 +1215,25 @@ void pf_ul(module_id_t module_id,
|
||||
if (max_num_ue < 0)
|
||||
return;
|
||||
|
||||
/* Save PUSCH field */
|
||||
/* we want to avoid a lengthy deduction of DMRS and other parameters in
|
||||
* every TTI if we can save it, so check whether dci_format, TDA, or
|
||||
* num_dmrs_cdm_grps_no_data has changed and only then recompute */
|
||||
const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2;
|
||||
int dci_format = get_dci_format(sched_ctrl);
|
||||
const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0;
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data
|
||||
|| sched_ctrl->update_pusch_ps) {
|
||||
nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
|
||||
sched_ctrl->update_pusch_ps = false;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC,"Looking for min_rb %d RBs, starting at %d\n", min_rb, rbStart);
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)))
|
||||
rbStart++;
|
||||
if (rbStart + min_rb >= bwpSize) {
|
||||
LOG_W(NR_MAC, "cannot allocate continuous UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
|
||||
UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
|
||||
@@ -1221,17 +1247,6 @@ void pf_ul(module_id_t module_id,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
|
||||
/* Save PUSCH field */
|
||||
/* we want to avoid a lengthy deduction of DMRS and other parameters in
|
||||
* every TTI if we can save it, so check whether dci_format, TDA, or
|
||||
* num_dmrs_cdm_grps_no_data has changed and only then recompute */
|
||||
const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2;
|
||||
int dci_format = get_dci_format(sched_ctrl);
|
||||
const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0;
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
|
||||
nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
sched_pusch->mcs = 9;
|
||||
update_ul_ue_R_Qm(sched_pusch, ps);
|
||||
@@ -1250,7 +1265,7 @@ void pf_ul(module_id_t module_id,
|
||||
/* Mark the corresponding RBs as used */
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -1325,19 +1340,6 @@ void pf_ul(module_id_t module_id,
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
|
||||
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
|
||||
sched_pusch->rbStart = rbStart;
|
||||
uint16_t max_rbSize = 1;
|
||||
while (rbStart + max_rbSize < bwpSize && rballoc_mask[rbStart + max_rbSize])
|
||||
max_rbSize++;
|
||||
|
||||
if (rbStart + min_rb >= bwpSize) {
|
||||
LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
|
||||
UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
|
||||
return;
|
||||
}
|
||||
else LOG_D(NR_MAC,"allocating UL data for UE %d/RNTI %04x (rbStsart %d, min_rb %d, bwpSize %d\n",UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
|
||||
|
||||
/* Save PUSCH field */
|
||||
/* we want to avoid a lengthy deduction of DMRS and other parameters in
|
||||
* every TTI if we can save it, so check whether dci_format, TDA, or
|
||||
@@ -1347,10 +1349,30 @@ void pf_ul(module_id_t module_id,
|
||||
const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0;
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data
|
||||
|| sched_ctrl->update_pusch_ps) {
|
||||
nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
|
||||
sched_ctrl->update_pusch_ps = false;
|
||||
}
|
||||
update_ul_ue_R_Qm(sched_pusch, ps);
|
||||
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)))
|
||||
rbStart++;
|
||||
sched_pusch->rbStart = rbStart;
|
||||
uint16_t max_rbSize = 1;
|
||||
while (rbStart + max_rbSize < bwpSize &&
|
||||
(rballoc_mask[rbStart + max_rbSize]&&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)))
|
||||
max_rbSize++;
|
||||
|
||||
if (rbStart + min_rb >= bwpSize) {
|
||||
LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
|
||||
UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
|
||||
return;
|
||||
}
|
||||
else LOG_D(NR_MAC,"allocating UL data for UE %d/RNTI %04x (rbStsart %d, min_rb %d, bwpSize %d\n",UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
|
||||
|
||||
|
||||
/* Calculate the current scheduling bytes and the necessary RBs */
|
||||
const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
|
||||
uint16_t rbSize = 0;
|
||||
@@ -1381,7 +1403,7 @@ void pf_ul(module_id_t module_id,
|
||||
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,11 +1486,9 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
|
||||
int startSymbolIndex, nrOfSymbols;
|
||||
SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
|
||||
const uint16_t symb = ((1 << nrOfSymbols) - 1) << startSymbolIndex;
|
||||
const uint16_t symb = SL_to_bitmap(startSymbolIndex, nrOfSymbols);
|
||||
|
||||
int st = 0, e = 0, len = 0;
|
||||
for (int i = 0; i < bwpSize; i++)
|
||||
if (RC.nrmac[module_id]->ulprbbl[i] == 1) vrb_map_UL[i]=symb;
|
||||
|
||||
for (int i = 0; i < bwpSize; i++) {
|
||||
while ((vrb_map_UL[bwpStart + i] & symb) != 0 && i < bwpSize)
|
||||
@@ -1485,11 +1505,11 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
|
||||
LOG_D(NR_MAC,"UL %d.%d : start_prb %d, end PRB %d\n",frame,slot,st,e);
|
||||
|
||||
uint8_t rballoc_mask[bwpSize];
|
||||
uint16_t rballoc_mask[bwpSize];
|
||||
|
||||
/* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */
|
||||
for (int i = 0; i < bwpSize; i++)
|
||||
rballoc_mask[i] = i >= st && i <= e;
|
||||
rballoc_mask[i] = (i >= st && i <= e)*SL_to_bitmap(startSymbolIndex, nrOfSymbols);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_ul(module_id,
|
||||
|
||||
@@ -291,6 +291,14 @@ void prepare_dci(const NR_CellGroupConfig_t *CellGroup,
|
||||
nr_dci_format_t format,
|
||||
int bwp_id);
|
||||
|
||||
void set_r_pucch_parms(int rsetindex,
|
||||
int r_pucch,
|
||||
int bwp_size,
|
||||
int *prb_start,
|
||||
int *second_hop_prb,
|
||||
int *nr_of_symbols,
|
||||
int *start_symbol_index);
|
||||
|
||||
/* find coreset within the search space */
|
||||
NR_ControlResourceSet_t *get_coreset(module_id_t module_idP,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
@@ -351,6 +359,7 @@ int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
/* Functions to manage an NR_list_t */
|
||||
void dump_nr_list(NR_list_t *listP);
|
||||
void create_nr_list(NR_list_t *listP, int len);
|
||||
void resize_nr_list(NR_list_t *list, int new_len);
|
||||
void destroy_nr_list(NR_list_t *list);
|
||||
void add_nr_list(NR_list_t *listP, int id);
|
||||
void remove_nr_list(NR_list_t *listP, int id);
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
/* PHY */
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/TOOLS/time_meas.h"
|
||||
#include "time_meas.h"
|
||||
|
||||
/* Interface */
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
@@ -171,6 +171,8 @@ typedef struct {
|
||||
uint8_t msg3_round;
|
||||
/// Flag to indicate if Msg3 carries a DCCH or DTCH message
|
||||
bool msg3_dcch_dtch;
|
||||
int msg3_startsymb;
|
||||
int msg3_nrsymb;
|
||||
/// TBS used for Msg4
|
||||
int msg4_TBsize;
|
||||
/// MCS used for Msg4
|
||||
@@ -327,6 +329,10 @@ typedef struct NR_sched_pucch {
|
||||
uint8_t timing_indicator;
|
||||
uint8_t resource_indicator;
|
||||
int r_pucch;
|
||||
int prb_start;
|
||||
int second_hop_prb;
|
||||
int nr_of_symb;
|
||||
int start_symb;
|
||||
} NR_sched_pucch_t;
|
||||
|
||||
/* PUSCH semi-static configuration: as long as the TDA and DCI format remain
|
||||
@@ -601,14 +607,13 @@ typedef struct {
|
||||
|
||||
/// total amount of data awaiting for this UE
|
||||
uint32_t num_total_bytes;
|
||||
uint16_t dl_pdus_total;
|
||||
/// per-LC status data
|
||||
mac_rlc_status_resp_t rlc_status[MAX_NUM_LCID];
|
||||
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
|
||||
|
||||
/// Estimation of HARQ from BLER
|
||||
NR_DL_bler_stats_t dl_bler_stats;
|
||||
|
||||
int lcid_mask;
|
||||
int lcid_to_schedule;
|
||||
uint16_t ta_frame;
|
||||
int16_t ta_update;
|
||||
bool ta_apply;
|
||||
@@ -624,6 +629,8 @@ typedef struct {
|
||||
int ul_failure;
|
||||
struct CSI_Report CSI_report;
|
||||
bool SR;
|
||||
bool update_pdsch_ps;
|
||||
bool update_pusch_ps;
|
||||
bool set_mcs;
|
||||
bool set_pmi;
|
||||
/// information about every HARQ process
|
||||
@@ -643,6 +650,12 @@ typedef struct {
|
||||
/// UL HARQ processes that await retransmission
|
||||
NR_list_t retrans_ul_harq;
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
||||
|
||||
/// number of active DL LCs
|
||||
uint8_t dl_lc_num;
|
||||
/// order in which DLSCH scheduler should allocate LCs
|
||||
uint8_t dl_lc_ids[NR_MAX_NUM_LCID];
|
||||
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -727,7 +740,7 @@ typedef struct gNB_MAC_INST_s {
|
||||
/// current PDU index (BCH,DLSCH)
|
||||
uint16_t pdu_index[NFAPI_CC_MAX];
|
||||
int num_ulprbbl;
|
||||
int ulprbbl[275];
|
||||
uint16_t ulprbbl[275];
|
||||
/// NFAPI Config Request Structure
|
||||
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
|
||||
/// NFAPI DL Config Request Structure
|
||||
|
||||
@@ -101,13 +101,6 @@ typedef struct {
|
||||
|
||||
static rlc_data_req_queue q;
|
||||
|
||||
extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const NR_SRB_ToAddModList_t * const srb2add_listP,
|
||||
const NR_DRB_ToAddModList_t * const drb2add_listP,
|
||||
const NR_DRB_ToReleaseList_t * const drb2release_listP,
|
||||
const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
static void *rlc_data_req_thread(void *_)
|
||||
{
|
||||
int i;
|
||||
@@ -1156,9 +1149,9 @@ void nr_DRB_preconfiguration(uint16_t crnti)
|
||||
drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer));
|
||||
*drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity;
|
||||
drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL));
|
||||
*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits;
|
||||
*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
|
||||
drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL));
|
||||
*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits;
|
||||
*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
|
||||
drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0;
|
||||
|
||||
@@ -1188,7 +1181,8 @@ void nr_DRB_preconfiguration(uint16_t crnti)
|
||||
|
||||
NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig));
|
||||
nr_rlc_bearer_init(RLC_BearerConfig,NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity);
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional);
|
||||
//nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
|
||||
nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig);
|
||||
|
||||
Rlc_Bearer_ToAdd_list = calloc(1,sizeof(*Rlc_Bearer_ToAdd_list));
|
||||
|
||||
@@ -1044,7 +1044,7 @@ next_pdu:
|
||||
set_end_different_sdu:
|
||||
/* don't go more than rx_highest_status - 1 */
|
||||
if (sn_compare_rx(entity, entity->rx_highest_status, cur->sn) <= 0) {
|
||||
ret.so_end = (entity->rx_highest_status - 1 + entity->sn_modulus) %
|
||||
ret.sn_end = (entity->rx_highest_status - 1 + entity->sn_modulus) %
|
||||
entity->sn_modulus;
|
||||
ret.so_end = 0xffff;
|
||||
return ret;
|
||||
@@ -1305,9 +1305,8 @@ static int missing_size(nr_rlc_entity_am_t *entity, missing_data_t *m,
|
||||
missing_data_t m_nack;
|
||||
|
||||
/* be careful to limit a range to 255 SNs, that is: cut if needed */
|
||||
sn_count = m->sn_end - m->sn_start + 1;
|
||||
if (sn_count < 0)
|
||||
sn_count += entity->sn_modulus;
|
||||
sn_count = (m->sn_end - m->sn_start + entity->sn_modulus)
|
||||
% entity->sn_modulus + 1;
|
||||
|
||||
sn_start = m->sn_start;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ extern uint16_t sl_ahead;
|
||||
|
||||
void handle_nr_rach(NR_UL_IND_t *UL_info)
|
||||
{
|
||||
if(NFAPI_MODE == NFAPI_MODE_PNF) {
|
||||
if (NFAPI_MODE == NFAPI_MODE_PNF) {
|
||||
if (UL_info->rach_ind.number_of_pdus > 0) {
|
||||
LOG_D(PHY,"UL_info->UL_info->rach_ind.number_of_pdus:%d SFN/Slot:%d.%d \n", UL_info->rach_ind.number_of_pdus, UL_info->rach_ind.sfn,UL_info->rach_ind.slot);
|
||||
oai_nfapi_nr_rach_indication(&UL_info->rach_ind);
|
||||
@@ -71,69 +71,29 @@ void handle_nr_rach(NR_UL_IND_t *UL_info)
|
||||
}
|
||||
return;
|
||||
}
|
||||
NR_UL_IND_t UL_INFO;
|
||||
nfapi_nr_rach_indication_t *rach_ind = NULL;
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
if (gnb_rach_ind_queue.num_items == 0)
|
||||
return;
|
||||
LOG_I(NR_MAC, "gnb_rach_ind_queue size = %zu\n", gnb_rach_ind_queue.num_items);
|
||||
rach_ind = get_queue(&gnb_rach_ind_queue);
|
||||
|
||||
UL_INFO.rach_ind = *rach_ind;
|
||||
UL_INFO.module_id = UL_info->module_id;
|
||||
UL_INFO.CC_id = UL_info->CC_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
UL_INFO.rach_ind = UL_info->rach_ind;
|
||||
UL_INFO.module_id = UL_info->module_id;
|
||||
UL_INFO.CC_id = UL_info->CC_id;
|
||||
}
|
||||
|
||||
int frame_diff = UL_info->frame - UL_INFO.rach_ind.sfn;
|
||||
if (frame_diff < 0)
|
||||
{
|
||||
int frame_diff = UL_info->frame - UL_info->rach_ind.sfn;
|
||||
if (frame_diff < 0) {
|
||||
frame_diff += 1024;
|
||||
}
|
||||
bool in_timewindow = frame_diff == 0 || (frame_diff == 1 && UL_info->slot < 7);
|
||||
|
||||
if (UL_INFO.rach_ind.number_of_pdus>0 && in_timewindow) {
|
||||
if (UL_info->rach_ind.number_of_pdus > 0 && in_timewindow) {
|
||||
LOG_A(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",
|
||||
UL_info->frame, UL_info->slot, UL_INFO.rach_ind.sfn, UL_INFO.rach_ind.slot);
|
||||
int npdus = UL_INFO.rach_ind.number_of_pdus;
|
||||
for(int i = 0; i < npdus; i++) {
|
||||
UL_INFO.rach_ind.number_of_pdus--;
|
||||
UL_info->frame, UL_info->slot, UL_info->rach_ind.sfn, UL_info->rach_ind.slot);
|
||||
for (int i = 0; i < UL_info->rach_ind.number_of_pdus; i++) {
|
||||
UL_info->rach_ind.number_of_pdus--;
|
||||
if (UL_INFO.rach_ind.pdu_list[i].num_preamble>0)
|
||||
AssertFatal(UL_INFO.rach_ind.pdu_list[i].num_preamble==1,
|
||||
"More than 1 preamble not supported\n");
|
||||
|
||||
nr_initiate_ra_proc(UL_INFO.module_id,
|
||||
UL_INFO.CC_id,
|
||||
UL_INFO.rach_ind.sfn,
|
||||
UL_INFO.rach_ind.slot,
|
||||
UL_INFO.rach_ind.pdu_list[i].preamble_list[0].preamble_index,
|
||||
UL_INFO.rach_ind.pdu_list[i].freq_index,
|
||||
UL_INFO.rach_ind.pdu_list[i].symbol_index,
|
||||
UL_INFO.rach_ind.pdu_list[i].preamble_list[0].timing_advance);
|
||||
AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble == 1, "More than 1 preamble not supported\n");
|
||||
nr_initiate_ra_proc(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
UL_info->rach_ind.sfn,
|
||||
UL_info->rach_ind.slot,
|
||||
UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index,
|
||||
UL_info->rach_ind.pdu_list[i].freq_index,
|
||||
UL_info->rach_ind.pdu_list[i].symbol_index,
|
||||
UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance);
|
||||
}
|
||||
}
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
if (rach_ind && rach_ind->number_of_pdus > 0)
|
||||
{
|
||||
for(int i = 0; i < rach_ind->number_of_pdus; i++)
|
||||
{
|
||||
free(rach_ind->pdu_list[i].preamble_list);
|
||||
rach_ind->pdu_list[i].preamble_list = NULL;
|
||||
}
|
||||
free(rach_ind->pdu_list);
|
||||
rach_ind->pdu_list = NULL;
|
||||
}
|
||||
free(rach_ind);
|
||||
rach_ind = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,26 +108,11 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
|
||||
return;
|
||||
}
|
||||
|
||||
NR_UL_IND_t UL_INFO;
|
||||
nfapi_nr_uci_indication_t *uci_ind = NULL;
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
if (gnb_uci_ind_queue.num_items == 0)
|
||||
return;
|
||||
LOG_I(NR_MAC, "gnb_uci_ind_queue size = %zu\n", gnb_uci_ind_queue.num_items);
|
||||
uci_ind = get_queue(&gnb_uci_ind_queue);
|
||||
UL_INFO.uci_ind = *uci_ind;
|
||||
}
|
||||
else
|
||||
{
|
||||
UL_INFO.uci_ind = UL_info->uci_ind;
|
||||
}
|
||||
|
||||
const module_id_t mod_id = UL_info->module_id;
|
||||
const frame_t frame = UL_INFO.uci_ind.sfn;
|
||||
const sub_frame_t slot = UL_INFO.uci_ind.slot;
|
||||
int num_ucis = UL_INFO.uci_ind.num_ucis;
|
||||
nfapi_nr_uci_t *uci_list = UL_INFO.uci_ind.uci_list;
|
||||
const frame_t frame = UL_info->uci_ind.sfn;
|
||||
const sub_frame_t slot = UL_info->uci_ind.slot;
|
||||
int num_ucis = UL_info->uci_ind.num_ucis;
|
||||
nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
|
||||
|
||||
for (int i = 0; i < num_ucis; i++) {
|
||||
switch (uci_list[i].pdu_type) {
|
||||
@@ -178,7 +123,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
|
||||
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
|
||||
const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
|
||||
LOG_D(NR_MAC, "The received uci has sfn slot %d %d, num_ucis %d and pdu_size %d\n",
|
||||
UL_INFO.uci_ind.sfn, UL_INFO.uci_ind.slot, num_ucis, uci_list[i].pdu_size);
|
||||
UL_info->uci_ind.sfn, UL_info->uci_ind.slot, num_ucis, uci_list[i].pdu_size);
|
||||
handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu);
|
||||
break;
|
||||
}
|
||||
@@ -192,39 +137,8 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
|
||||
}
|
||||
}
|
||||
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
for (int i = 0; i < num_ucis; i++) {
|
||||
switch (uci_list[i].pdu_type) {
|
||||
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE:
|
||||
if (uci_list[i].pucch_pdu_format_0_1.harq) {
|
||||
free(uci_list[i].pucch_pdu_format_0_1.harq->harq_list);
|
||||
uci_list[i].pucch_pdu_format_0_1.harq->harq_list = NULL;
|
||||
}
|
||||
free(uci_list[i].pucch_pdu_format_0_1.harq);
|
||||
uci_list[i].pucch_pdu_format_0_1.harq = NULL;
|
||||
free(uci_list[i].pucch_pdu_format_0_1.sr);
|
||||
uci_list[i].pucch_pdu_format_0_1.sr = NULL;
|
||||
break;
|
||||
UL_info->uci_ind.num_ucis = 0;
|
||||
|
||||
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE:
|
||||
free(uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload);
|
||||
free(uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload);
|
||||
free(uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uci_ind && num_ucis > 0) {
|
||||
free(uci_list);
|
||||
uci_list = NULL;
|
||||
}
|
||||
free(uci_ind);
|
||||
uci_ind = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
UL_info->uci_ind.num_ucis = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool crc_sfn_slot_matcher(void *wanted, void *candidate)
|
||||
@@ -264,173 +178,202 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info)
|
||||
return;
|
||||
}
|
||||
|
||||
NR_UL_IND_t UL_INFO;
|
||||
nfapi_nr_rx_data_indication_t *rx_ind = NULL;
|
||||
nfapi_nr_crc_indication_t *crc_ind = NULL;
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
rx_ind = get_queue(&gnb_rx_ind_queue);
|
||||
if (!rx_ind)
|
||||
{
|
||||
LOG_D(NR_PHY, "No rx data indication (empty gnb_rx_ind_queue)\n");
|
||||
return;
|
||||
if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
|
||||
AssertFatal(UL_info->rx_ind.number_of_pdus == UL_info->crc_ind.number_crcs,
|
||||
"number_of_pdus %d, number_crcs %d\n",
|
||||
UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs);
|
||||
for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) {
|
||||
const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i];
|
||||
const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[i];
|
||||
LOG_D(NR_PHY, "UL_info->crc_ind.pdu_list[%d].rnti:%04x "
|
||||
"UL_info->rx_ind.pdu_list[%d].rnti:%04x\n",
|
||||
i, crc->rnti, i, rx->rnti);
|
||||
|
||||
AssertFatal(crc->rnti == rx->rnti, "mis-match between CRC RNTI %04x and RX RNTI %04x\n",
|
||||
crc->rnti, rx->rnti);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n",
|
||||
UL_info->frame,
|
||||
UL_info->slot,
|
||||
crc->tb_crc_status ? "error" : "ok",
|
||||
crc->tb_crc_status);
|
||||
|
||||
/* if CRC passes, pass PDU, otherwise pass NULL as error indication */
|
||||
nr_rx_sdu(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
UL_info->rx_ind.sfn,
|
||||
UL_info->rx_ind.slot,
|
||||
rx->rnti,
|
||||
crc->tb_crc_status ? NULL : rx->pdu,
|
||||
rx->pdu_length,
|
||||
rx->timing_advance,
|
||||
rx->ul_cqi,
|
||||
rx->rssi);
|
||||
handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc);
|
||||
}
|
||||
|
||||
int sfn_slot = NFAPI_SFNSLOT2HEX(rx_ind->sfn, rx_ind->slot);
|
||||
|
||||
crc_ind = unqueue_matching(&gnb_crc_ind_queue,
|
||||
MAX_QUEUE_SIZE,
|
||||
crc_sfn_slot_matcher,
|
||||
&sfn_slot);
|
||||
if (!crc_ind)
|
||||
{
|
||||
LOG_D(NR_PHY, "No crc indication with the same SFN SLOT of rx indication %u %u\n", rx_ind->sfn, rx_ind->slot);
|
||||
put_queue(&gnb_rx_ind_queue, rx_ind);
|
||||
return;
|
||||
}
|
||||
|
||||
UL_INFO.rx_ind = *rx_ind;
|
||||
UL_INFO.crc_ind = *crc_ind;
|
||||
UL_INFO.module_id = UL_info->module_id;
|
||||
UL_INFO.CC_id = UL_info->CC_id;
|
||||
}
|
||||
else
|
||||
UL_info->rx_ind.number_of_pdus = 0;
|
||||
UL_info->crc_ind.number_crcs = 0;
|
||||
}
|
||||
|
||||
static void free_unqueued_nfapi_indications(nfapi_nr_rach_indication_t *rach_ind,
|
||||
nfapi_nr_uci_indication_t *uci_ind,
|
||||
nfapi_nr_rx_data_indication_t *rx_ind,
|
||||
nfapi_nr_crc_indication_t *crc_ind) {
|
||||
if (rach_ind && rach_ind->number_of_pdus > 0)
|
||||
{
|
||||
UL_INFO.rx_ind = UL_info->rx_ind;
|
||||
UL_INFO.crc_ind = UL_info->crc_ind;
|
||||
UL_INFO.module_id = UL_info->module_id;
|
||||
UL_INFO.CC_id = UL_info->CC_id;
|
||||
for(int i = 0; i < rach_ind->number_of_pdus; i++)
|
||||
{
|
||||
free_and_zero(rach_ind->pdu_list[i].preamble_list);
|
||||
}
|
||||
free_and_zero(rach_ind->pdu_list);
|
||||
free_and_zero(rach_ind);
|
||||
}
|
||||
if (uci_ind && uci_ind->num_ucis > 0)
|
||||
{
|
||||
for (int i = 0; i < uci_ind->num_ucis; i++) {
|
||||
switch (uci_ind->uci_list[i].pdu_type) {
|
||||
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE:
|
||||
if (uci_ind->uci_list[i].pucch_pdu_format_0_1.harq) {
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_0_1.harq->harq_list);
|
||||
}
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_0_1.harq);
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_0_1.sr);
|
||||
break;
|
||||
|
||||
UL_INFO.frame = UL_INFO.rx_ind.sfn;
|
||||
UL_INFO.slot = UL_INFO.rx_ind.slot;
|
||||
UL_INFO.module_id = UL_info->module_id;
|
||||
UL_INFO.CC_id = UL_info->CC_id;
|
||||
LOG_D(NR_MAC, " UL_info frame slot vs rx_ind frame slot vs crc_ind slot frame slot = %u %u vs %u %u vs %u %u\n",
|
||||
UL_info->frame, UL_info->slot,
|
||||
UL_INFO.rx_ind.sfn, UL_INFO.rx_ind.slot,
|
||||
UL_INFO.crc_ind.sfn, UL_INFO.crc_ind.slot
|
||||
);
|
||||
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE:
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload);
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload);
|
||||
free_and_zero(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free_and_zero(uci_ind->uci_list);
|
||||
free_and_zero(uci_ind);
|
||||
}
|
||||
if (rx_ind && rx_ind->number_of_pdus > 0)
|
||||
{
|
||||
free_and_zero(rx_ind->pdu_list);
|
||||
free_and_zero(rx_ind);
|
||||
}
|
||||
if (crc_ind && crc_ind->number_crcs > 0)
|
||||
{
|
||||
free_and_zero(crc_ind->crc_list);
|
||||
free_and_zero(crc_ind);
|
||||
}
|
||||
}
|
||||
|
||||
if (UL_INFO.rx_ind.number_of_pdus > 0 && UL_INFO.crc_ind.number_crcs > 0) {
|
||||
for (int i = 0; i < UL_INFO.rx_ind.number_of_pdus; i++) {
|
||||
int j;
|
||||
for (j = 0; j < UL_INFO.crc_ind.number_crcs; j++) {
|
||||
// find crc_indication j corresponding rx_indication i
|
||||
const nfapi_nr_rx_data_pdu_t *rx = &UL_INFO.rx_ind.pdu_list[i];
|
||||
const nfapi_nr_crc_t *crc = &UL_INFO.crc_ind.crc_list[j];
|
||||
LOG_D(NR_PHY,
|
||||
"UL_INFO.crc_ind.pdu_list[%d].rnti:%04x "
|
||||
"UL_INFO.rx_ind.pdu_list[%d].rnti:%04x\n",
|
||||
j,
|
||||
crc->rnti,
|
||||
i,
|
||||
rx->rnti);
|
||||
static void remove_crc_pdu(nfapi_nr_crc_indication_t *crc_ind, int index) {
|
||||
AssertFatal(index >= 0, "Invalid index %d\n", index);
|
||||
AssertFatal(index < crc_ind->number_crcs, "Invalid index %d\n", index);
|
||||
AssertFatal(crc_ind->number_crcs > 0, "Invalid crc_ind->number_crcs %d\n", crc_ind->number_crcs);
|
||||
|
||||
if (crc->rnti != rx->rnti)
|
||||
{
|
||||
LOG_D(NR_MAC, "mis-match between CRC rnti %04x and RX rnit %04x\n", crc->rnti, rx->rnti);
|
||||
continue;
|
||||
}
|
||||
memmove(crc_ind->crc_list + index,
|
||||
crc_ind->crc_list + index + 1,
|
||||
sizeof(*crc_ind->crc_list) * (crc_ind->number_crcs - index - 1));
|
||||
crc_ind->number_crcs--;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n",
|
||||
UL_INFO.frame,
|
||||
UL_INFO.slot,
|
||||
crc->tb_crc_status ? "error" : "ok",
|
||||
crc->tb_crc_status);
|
||||
static void remove_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, int index) {
|
||||
AssertFatal(index >= 0, "Invalid index %d\n", index);
|
||||
AssertFatal(index < rx_ind->number_of_pdus, "Invalid index %d\n", index);
|
||||
AssertFatal(rx_ind->number_of_pdus > 0, "Invalid rx_ind->number_of_pdus %d\n", rx_ind->number_of_pdus);
|
||||
|
||||
/* if CRC passes, pass PDU, otherwise pass NULL as error indication */
|
||||
nr_rx_sdu(UL_INFO.module_id,
|
||||
UL_INFO.CC_id,
|
||||
UL_INFO.rx_ind.sfn,
|
||||
UL_INFO.rx_ind.slot,
|
||||
rx->rnti,
|
||||
crc->tb_crc_status ? NULL : rx->pdu,
|
||||
rx->pdu_length,
|
||||
rx->timing_advance,
|
||||
rx->ul_cqi,
|
||||
rx->rssi);
|
||||
handle_nr_ul_harq(UL_INFO.CC_id, UL_INFO.module_id, UL_INFO.frame, UL_INFO.slot, crc);
|
||||
memmove(rx_ind->pdu_list + index,
|
||||
rx_ind->pdu_list + index + 1,
|
||||
sizeof(*rx_ind->pdu_list) * (rx_ind->number_of_pdus - index - 1));
|
||||
rx_ind->number_of_pdus--;
|
||||
}
|
||||
|
||||
static bool crc_ind_has_rnti(nfapi_nr_crc_indication_t *crc_ind, uint16_t rnti) {
|
||||
for (int i = 0; i < crc_ind->number_crcs; i++) {
|
||||
if (rnti == crc_ind->crc_list[i].rnti) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rx_ind_has_rnti(nfapi_nr_rx_data_indication_t *rx_ind, uint16_t rnti) {
|
||||
for (int i = 0; i < rx_ind->number_of_pdus; i++) {
|
||||
if (rnti == rx_ind->pdu_list[i].rnti) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc_indication_t *crc_ind) {
|
||||
AssertFatal(crc_ind->number_crcs > 0 && rx_ind->number_of_pdus > 0,
|
||||
"Invalid number of crc_ind->number_crcs %d or rx_ind->number_of_pdus %d\n",
|
||||
crc_ind->number_crcs, rx_ind->number_of_pdus);
|
||||
if (crc_ind->number_crcs > rx_ind->number_of_pdus) {
|
||||
int num_unmatched_crcs = 0;
|
||||
nfapi_nr_crc_indication_t *crc_ind_unmatched = calloc(1, sizeof(*crc_ind_unmatched));
|
||||
crc_ind_unmatched->header = crc_ind->header;
|
||||
crc_ind_unmatched->sfn = crc_ind->sfn;
|
||||
crc_ind_unmatched->slot = crc_ind->slot;
|
||||
crc_ind_unmatched->number_crcs = crc_ind->number_crcs - rx_ind->number_of_pdus;
|
||||
crc_ind_unmatched->crc_list = calloc(crc_ind_unmatched->number_crcs, sizeof(nfapi_nr_crc_t));
|
||||
for (int i = 0; i < crc_ind->number_crcs; i++) {
|
||||
if (!rx_ind_has_rnti(rx_ind, crc_ind->crc_list[i].rnti)) {
|
||||
LOG_I(NR_MAC, "crc_ind->crc_list[%d].rnti %x does not match any rx_ind pdu rnti\n",
|
||||
i, crc_ind->crc_list[i].rnti);
|
||||
crc_ind_unmatched->crc_list[num_unmatched_crcs] = crc_ind->crc_list[i];
|
||||
num_unmatched_crcs++;
|
||||
remove_crc_pdu(crc_ind, i);
|
||||
}
|
||||
if (crc_ind->number_crcs == rx_ind->number_of_pdus) {
|
||||
break;
|
||||
} // for (j=0;j<UL_INFO.crc_ind.number_crcs;j++)
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
int last = UL_INFO.crc_ind.number_crcs - 1;
|
||||
if (j < last)
|
||||
{
|
||||
crc_ind->crc_list[j] = crc_ind->crc_list[last];
|
||||
UL_INFO.crc_ind.number_crcs--;
|
||||
}
|
||||
else if (j == last)
|
||||
{
|
||||
UL_INFO.crc_ind.number_crcs--;
|
||||
}
|
||||
|
||||
last = UL_INFO.rx_ind.number_of_pdus - 1;
|
||||
if (i < last)
|
||||
{
|
||||
rx_ind->pdu_list[i] = rx_ind->pdu_list[last];
|
||||
UL_INFO.rx_ind.number_of_pdus--;
|
||||
i--;
|
||||
}
|
||||
else if (i == last)
|
||||
{
|
||||
UL_INFO.rx_ind.number_of_pdus--;
|
||||
}
|
||||
}
|
||||
} // for (i=0;i<UL_INFO.rx_ind.number_of_pdus;i++)
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
if (UL_INFO.crc_ind.number_crcs > 0)
|
||||
{
|
||||
crc_ind->number_crcs = UL_INFO.crc_ind.number_crcs;
|
||||
requeue(&gnb_crc_ind_queue, crc_ind);
|
||||
}
|
||||
|
||||
if (UL_INFO.rx_ind.number_of_pdus > 0)
|
||||
{
|
||||
rx_ind->number_of_pdus = UL_INFO.rx_ind.number_of_pdus;
|
||||
requeue(&gnb_rx_ind_queue, rx_ind);
|
||||
}
|
||||
|
||||
if (UL_INFO.crc_ind.number_crcs == 0)
|
||||
{
|
||||
free(crc_ind->crc_list);
|
||||
crc_ind->crc_list = NULL;
|
||||
free(crc_ind);
|
||||
crc_ind = NULL;
|
||||
}
|
||||
if (UL_INFO.rx_ind.number_of_pdus == 0)
|
||||
{
|
||||
free(rx_ind->pdu_list);
|
||||
rx_ind->pdu_list = NULL;
|
||||
free(rx_ind);
|
||||
rx_ind = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
AssertFatal(crc_ind_unmatched->number_crcs == num_unmatched_crcs, "crc_ind num_pdus %d doesnt match %d\n",
|
||||
crc_ind_unmatched->number_crcs, num_unmatched_crcs);
|
||||
if (!requeue(&gnb_crc_ind_queue, crc_ind_unmatched))
|
||||
{
|
||||
UL_info->crc_ind.number_crcs = 0;
|
||||
UL_info->rx_ind.number_of_pdus = 0;
|
||||
LOG_E(NR_PHY, "requeue failed for crc_ind_unmatched.\n");
|
||||
free_and_zero(crc_ind_unmatched->crc_list);
|
||||
free_and_zero(crc_ind_unmatched);
|
||||
}
|
||||
} else if ((UL_INFO.rx_ind.number_of_pdus != 0)
|
||||
|| (UL_INFO.crc_ind.number_crcs != 0)) {
|
||||
LOG_E(NR_PHY,
|
||||
"hoping not to have mis-match between CRC ind and RX ind - "
|
||||
"hopefully the missing message is coming shortly "
|
||||
"rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n",
|
||||
UL_INFO.rx_ind.number_of_pdus,
|
||||
UL_INFO.rx_ind.sfn,
|
||||
UL_INFO.rx_ind.slot,
|
||||
UL_INFO.crc_ind.number_crcs,
|
||||
UL_INFO.crc_ind.sfn,
|
||||
UL_INFO.crc_ind.slot);
|
||||
}
|
||||
else if (crc_ind->number_crcs < rx_ind->number_of_pdus) {
|
||||
int num_unmatched_rxs = 0;
|
||||
nfapi_nr_rx_data_indication_t *rx_ind_unmatched = calloc(1, sizeof(*rx_ind_unmatched));
|
||||
rx_ind_unmatched->header = rx_ind->header;
|
||||
rx_ind_unmatched->sfn = rx_ind->sfn;
|
||||
rx_ind_unmatched->slot = rx_ind->slot;
|
||||
rx_ind_unmatched->number_of_pdus = rx_ind->number_of_pdus - crc_ind->number_crcs;
|
||||
rx_ind_unmatched->pdu_list = calloc(rx_ind_unmatched->number_of_pdus, sizeof(nfapi_nr_pdu_t));
|
||||
for (int i = 0; i < rx_ind->number_of_pdus; i++) {
|
||||
if (!crc_ind_has_rnti(crc_ind, rx_ind->pdu_list[i].rnti)) {
|
||||
LOG_I(NR_MAC, "rx_ind->pdu_list[%d].rnti %d does not match any crc_ind pdu rnti\n",
|
||||
i, rx_ind->pdu_list[i].rnti);
|
||||
rx_ind_unmatched->pdu_list[num_unmatched_rxs] = rx_ind->pdu_list[i];
|
||||
num_unmatched_rxs++;
|
||||
remove_rx_pdu(rx_ind, i);
|
||||
}
|
||||
if (rx_ind->number_of_pdus == crc_ind->number_crcs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertFatal(rx_ind_unmatched->number_of_pdus == num_unmatched_rxs, "rx_ind num_pdus %d doesnt match %d\n",
|
||||
rx_ind_unmatched->number_of_pdus, num_unmatched_rxs);
|
||||
if (!requeue(&gnb_rx_ind_queue, rx_ind_unmatched))
|
||||
{
|
||||
LOG_E(NR_PHY, "requeue failed for rx_ind_unmatched.\n");
|
||||
free_and_zero(rx_ind_unmatched->pdu_list);
|
||||
free_and_zero(rx_ind_unmatched);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_E(NR_MAC, "The number of crc pdus %d = the number of rx pdus %d\n",
|
||||
crc_ind->number_crcs, rx_ind->number_of_pdus);
|
||||
}
|
||||
}
|
||||
|
||||
void NR_UL_indication(NR_UL_IND_t *UL_info) {
|
||||
AssertFatal(UL_info!=NULL,"UL_INFO is null\n");
|
||||
AssertFatal(UL_info!=NULL,"UL_info is null\n");
|
||||
#ifdef DUMP_FAPI
|
||||
dump_ul(UL_info);
|
||||
#endif
|
||||
@@ -440,17 +383,63 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) {
|
||||
NR_IF_Module_t *ifi = nr_if_inst[module_id];
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
LOG_D(NR_PHY,"SFN/SLOT:%d.%d module_id:%d CC_id:%d UL_info[rach_pdus:%zu rx_ind:%zu crcs:%zu]\n",
|
||||
UL_info->frame,UL_info->slot,
|
||||
module_id,CC_id, gnb_rach_ind_queue.num_items,
|
||||
gnb_rx_ind_queue.num_items, gnb_crc_ind_queue.num_items);
|
||||
UL_info->frame, UL_info->slot,
|
||||
module_id, CC_id,
|
||||
gnb_rach_ind_queue.num_items,
|
||||
gnb_rx_ind_queue.num_items,
|
||||
gnb_crc_ind_queue.num_items);
|
||||
|
||||
nfapi_nr_rach_indication_t *rach_ind = NULL;
|
||||
nfapi_nr_uci_indication_t *uci_ind = NULL;
|
||||
nfapi_nr_rx_data_indication_t *rx_ind = NULL;
|
||||
nfapi_nr_crc_indication_t *crc_ind = NULL;
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
{
|
||||
if (gnb_rach_ind_queue.num_items > 0) {
|
||||
LOG_D(NR_MAC, "gnb_rach_ind_queue size = %zu\n", gnb_rach_ind_queue.num_items);
|
||||
rach_ind = get_queue(&gnb_rach_ind_queue);
|
||||
AssertFatal(rach_ind->number_of_pdus > 0, "Invalid number of PDUs\n");
|
||||
UL_info->rach_ind = *rach_ind;
|
||||
}
|
||||
if (gnb_uci_ind_queue.num_items > 0) {
|
||||
LOG_D(NR_MAC, "gnb_uci_ind_queue size = %zu\n", gnb_uci_ind_queue.num_items);
|
||||
uci_ind = get_queue(&gnb_uci_ind_queue);
|
||||
AssertFatal(uci_ind->num_ucis > 0, "Invalid number of PDUs\n");
|
||||
UL_info->uci_ind = *uci_ind;
|
||||
}
|
||||
if (gnb_rx_ind_queue.num_items > 0 && gnb_crc_ind_queue.num_items > 0) {
|
||||
LOG_D(NR_MAC, "gnb_rx_ind_queue size = %zu and gnb_crc_ind_queue size = %zu\n",
|
||||
gnb_rx_ind_queue.num_items, gnb_crc_ind_queue.num_items);
|
||||
rx_ind = get_queue(&gnb_rx_ind_queue);
|
||||
int sfn_slot = NFAPI_SFNSLOT2HEX(rx_ind->sfn, rx_ind->slot);
|
||||
crc_ind = unqueue_matching(&gnb_crc_ind_queue,
|
||||
MAX_QUEUE_SIZE,
|
||||
crc_sfn_slot_matcher,
|
||||
&sfn_slot);
|
||||
if (!crc_ind) {
|
||||
LOG_I(NR_PHY, "No crc indication with the same SFN SLOT of rx indication %u %u\n", rx_ind->sfn, rx_ind->slot);
|
||||
requeue(&gnb_rx_ind_queue, rx_ind);
|
||||
}
|
||||
else {
|
||||
AssertFatal(rx_ind->number_of_pdus > 0, "Invalid number of PDUs\n");
|
||||
AssertFatal(crc_ind->number_crcs > 0, "Invalid number of PDUs\n");
|
||||
if (crc_ind->number_crcs != rx_ind->number_of_pdus)
|
||||
match_crc_rx_pdu(rx_ind, crc_ind);
|
||||
UL_info->rx_ind = *rx_ind;
|
||||
UL_info->crc_ind = *crc_ind;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle_nr_rach(UL_info);
|
||||
|
||||
handle_nr_uci(UL_info);
|
||||
// clear UL DCI prior to handling ULSCH
|
||||
mac->UL_dci_req[CC_id].numPdus = 0;
|
||||
handle_nr_ulsch(UL_info);
|
||||
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
free_unqueued_nfapi_indications(rach_ind, uci_ind, rx_ind, crc_ind);
|
||||
}
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
|
||||
if (ifi->CC_mask==0) {
|
||||
|
||||
@@ -296,11 +296,11 @@ static void copy_dl_tti_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id);
|
||||
mac->nr_ue_emul_l1.expected_sib = false;
|
||||
memset(mac->nr_ue_emul_l1.index_has_sib, 0, sizeof(*mac->nr_ue_emul_l1.index_has_sib));
|
||||
memset(mac->nr_ue_emul_l1.index_has_sib, 0, sizeof(mac->nr_ue_emul_l1.index_has_sib));
|
||||
mac->nr_ue_emul_l1.expected_rar = false;
|
||||
memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(*mac->nr_ue_emul_l1.index_has_rar));
|
||||
memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(mac->nr_ue_emul_l1.index_has_rar));
|
||||
mac->nr_ue_emul_l1.expected_dci = false;
|
||||
memset(mac->nr_ue_emul_l1.index_has_dci, 0, sizeof(*mac->nr_ue_emul_l1.index_has_dci));
|
||||
memset(mac->nr_ue_emul_l1.index_has_dci, 0, sizeof(mac->nr_ue_emul_l1.index_has_dci));
|
||||
int pdu_idx = 0;
|
||||
|
||||
int num_pdus = dl_tti_request->dl_tti_request_body.nPDUs;
|
||||
@@ -424,7 +424,7 @@ static void copy_tx_data_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi
|
||||
|
||||
if (!dl_info->rx_ind)
|
||||
{
|
||||
dl_info->rx_ind = CALLOC(1, sizeof(fapi_nr_rx_indication_t));
|
||||
dl_info->rx_ind = CALLOC(num_pdus, sizeof(fapi_nr_rx_indication_t));
|
||||
}
|
||||
AssertFatal(dl_info->rx_ind != NULL, "%s: Out of memory in calloc", __FUNCTION__);
|
||||
fapi_nr_rx_indication_t *rx_ind = dl_info->rx_ind;
|
||||
@@ -1038,7 +1038,8 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t
|
||||
// Note: sdu should always be processed because data and timing advance updates are transmitted by the UE
|
||||
int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
|
||||
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid = g_harq_pid;
|
||||
if (get_softmodem_params()->emulate_l1)
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid = g_harq_pid;
|
||||
|
||||
update_harq_status(dl_info->module_id,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
|
||||
@@ -1174,7 +1175,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,
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __OPENAIR2_PHY_INTERFACE_QUEUE_T__H__
|
||||
#define __OPENAIR2_PHY_INTERFACE_QUEUE_T__H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -62,3 +63,5 @@ typedef bool queue_matcher_t(void *wanted, void *candidate);
|
||||
Look only at the last `max_depth` items on the queue, at most.
|
||||
Returns the candidate item, or NULL if none matches */
|
||||
void *unqueue_matching(queue_t *q, size_t max_depth, queue_matcher_t *matcher, void *wanted);
|
||||
|
||||
#endif /* __OPENAIR2_PHY_INTERFACE_QUEUE_T__H__ */
|
||||
|
||||
@@ -4293,9 +4293,11 @@ ssize_t do_nrMeasurementReport(uint8_t *buffer,
|
||||
LTE_MeasResultListEUTRA_t *measResultListEUTRA2=&measResultNeighCells->choice.measResultListEUTRA;
|
||||
asn1cSequenceAdd(measResultListEUTRA2->list, struct LTE_MeasResultEUTRA, measresulteutra_list);
|
||||
measresulteutra_list->physCellId = phy_id;
|
||||
//asn1cCalloc(measresulteutra_list->cgi_Info, measresult_cgi2);
|
||||
//measresult_cgi2->cellGlobalId= {0};
|
||||
//measresult_cgi2->trackingAreaCode= {0};
|
||||
/* TODO: This asn1cCalloc leaks memory but also masks a bug.
|
||||
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);
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
* \email: raymond.knopp@eurecom.fr and navid.nikaein@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef __RRC_LTE_MESSAGES_ASN1_MSG__H__
|
||||
#define __RRC_LTE_MESSAGES_ASN1_MSG__H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h> /* for atoi(3) */
|
||||
@@ -405,3 +408,5 @@ uint8_t do_SecurityModeCommand(
|
||||
const uint8_t Transaction_id,
|
||||
const uint8_t cipheringAlgorithm,
|
||||
const uint8_t integrityProtAlgorithm);
|
||||
|
||||
#endif /* __RRC_LTE_MESSAGES_ASN1_MSG__H__ */
|
||||
|
||||
@@ -321,7 +321,7 @@ int8_t nr_mac_rrc_data_ind(const module_id_t module_idP,
|
||||
ue_context_p->ue_context.Srb0.Active = 1;
|
||||
RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[module_idP]->rrc_ue_head, ue_context_p);
|
||||
|
||||
fill_initial_cellGroupConfig(ue_context_p->local_uid,&cellGroupConfig,scc,&RC.nrrrc[module_idP]->carrier);
|
||||
fill_initial_cellGroupConfig(ue_context_p->local_uid,&cellGroupConfig,scc, &RC.nrrrc[module_idP]->configuration);
|
||||
|
||||
MessageDef* tmp=itti_alloc_new_message_sized(TASK_RRC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE, sizeof(f1ap_initial_ul_rrc_message_t) + sdu_lenP);
|
||||
f1ap_initial_ul_rrc_message_t *msg = &F1AP_INITIAL_UL_RRC_MESSAGE(tmp);
|
||||
|
||||
@@ -197,6 +197,7 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) {
|
||||
|
||||
asn_enc_rval_t enc_rval;
|
||||
rrc_gNB_carrier_data_t *carrier = &rrc->carrier;
|
||||
const gNB_RrcConfigurationReq *configuration = &rrc->configuration;
|
||||
|
||||
NR_BCCH_BCH_Message_t *mib = &carrier->mib;
|
||||
NR_ServingCellConfigCommon_t *scc = carrier->servingcellconfigcommon;
|
||||
@@ -220,7 +221,7 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) {
|
||||
mib->message.choice.mib->spare.size = 1;
|
||||
mib->message.choice.mib->spare.bits_unused = 7; // This makes a spare of 1 bits
|
||||
|
||||
mib->message.choice.mib->ssb_SubcarrierOffset = (carrier->ssb_SubcarrierOffset)&15;
|
||||
mib->message.choice.mib->ssb_SubcarrierOffset = (configuration->ssb_SubcarrierOffset)&15;
|
||||
|
||||
/*
|
||||
* The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables
|
||||
@@ -1007,8 +1008,8 @@ long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) {
|
||||
void fill_initial_SpCellConfig(int uid,
|
||||
NR_SpCellConfig_t *SpCellConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier) {
|
||||
|
||||
const gNB_RrcConfigurationReq *configuration)
|
||||
{
|
||||
// This assert will never happen in the current implementation because NUMBER_OF_UE_MAX = 4.
|
||||
// However, if in the future NUMBER_OF_UE_MAX is increased, it will be necessary to improve the allocation of SRS resources,
|
||||
// where the startPosition = 2 or 3 and sl160 = 17, 17, 27 ... 157 only give us 30 different allocations.
|
||||
@@ -1139,7 +1140,7 @@ void fill_initial_SpCellConfig(int uid,
|
||||
ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id);
|
||||
srs_Config->srs_ResourceToReleaseList=NULL;
|
||||
|
||||
if(carrier->do_SRS) {
|
||||
if (configuration->do_SRS) {
|
||||
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic;
|
||||
srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
|
||||
srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
|
||||
@@ -1183,7 +1184,7 @@ void fill_initial_SpCellConfig(int uid,
|
||||
srs_res0->freqHopping.b_SRS);
|
||||
srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither;
|
||||
|
||||
if(carrier->do_SRS) {
|
||||
if (configuration->do_SRS) {
|
||||
srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_periodic;
|
||||
srs_res0->resourceType.choice.periodic=calloc(1,sizeof(*srs_res0->resourceType.choice.periodic));
|
||||
srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
|
||||
@@ -1229,9 +1230,9 @@ void fill_initial_SpCellConfig(int uid,
|
||||
long *delay[8];
|
||||
for (int i=0;i<8;i++) {
|
||||
delay[i] = calloc(1,sizeof(*delay[i]));
|
||||
AssertFatal(carrier->minRXTXTIME >=2 && carrier->minRXTXTIME <7,
|
||||
"check minRXTXTIME %d\n",carrier->minRXTXTIME);
|
||||
*delay[i] = (i+carrier->minRXTXTIME);
|
||||
AssertFatal(configuration->minRXTXTIME >= 2 && configuration->minRXTXTIME < 7,
|
||||
"minRXTXTIME is %d but should be within [2,7)\n", configuration->minRXTXTIME);
|
||||
*delay[i] = i + configuration->minRXTXTIME;
|
||||
ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]);
|
||||
}
|
||||
|
||||
@@ -1451,11 +1452,36 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr
|
||||
ASN_SEQUENCE_ADD(&ue_context_mastercellGroup->rlc_BearerToAddModList->list, rlc_BearerConfig_drb);
|
||||
}
|
||||
|
||||
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
rrc_gNB_carrier_data_t *carrier,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
const gNB_RrcConfigurationReq* configuration)
|
||||
{
|
||||
NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig;
|
||||
if (SpCellConfig == NULL) return;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = carrier->servingcellconfigcommon;
|
||||
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP;
|
||||
set_dl_mcs_table(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing,
|
||||
configuration->force_256qam_off ? NULL : uecap, bwp_Dedicated, scc);
|
||||
|
||||
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *DL_BWP_list = SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
|
||||
if (DL_BWP_list) {
|
||||
for (int i=0; i<DL_BWP_list->list.count; i++){
|
||||
NR_BWP_Downlink_t *bwp = DL_BWP_list->list.array[i];
|
||||
int scs = bwp->bwp_Common->genericParameters.subcarrierSpacing;
|
||||
set_dl_mcs_table(scs, configuration->force_256qam_off ? NULL : uecap, bwp->bwp_Dedicated, carrier->servingcellconfigcommon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fill_initial_cellGroupConfig(int uid,
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier) {
|
||||
|
||||
const gNB_RrcConfigurationReq *configuration)
|
||||
{
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL;
|
||||
NR_RLC_Config_t *rlc_Config = NULL;
|
||||
NR_LogicalChannelConfig_t *logicalChannelConfig = NULL;
|
||||
@@ -1545,7 +1571,7 @@ void fill_initial_cellGroupConfig(int uid,
|
||||
|
||||
cellGroupConfig->spCellConfig = calloc(1,sizeof(*cellGroupConfig->spCellConfig));
|
||||
|
||||
fill_initial_SpCellConfig(uid,cellGroupConfig->spCellConfig,scc,carrier);
|
||||
fill_initial_SpCellConfig(uid,cellGroupConfig->spCellConfig,scc,configuration);
|
||||
|
||||
cellGroupConfig->sCellToAddModList = NULL;
|
||||
cellGroupConfig->sCellToReleaseList = NULL;
|
||||
@@ -1557,7 +1583,7 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
const uint8_t transaction_id,
|
||||
OCTET_STRING_t *masterCellGroup_from_DU,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier)
|
||||
const gNB_RrcConfigurationReq *configuration)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
asn_enc_rval_t enc_rval;
|
||||
@@ -1624,7 +1650,7 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
}
|
||||
else {
|
||||
cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
|
||||
fill_initial_cellGroupConfig(ue_context_pP->local_uid,cellGroupConfig,scc,carrier);
|
||||
fill_initial_cellGroupConfig(ue_context_pP->local_uid, cellGroupConfig, scc, configuration);
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
|
||||
NULL,
|
||||
@@ -1870,6 +1896,9 @@ int16_t do_RRCReconfiguration(
|
||||
NR_SDAP_Config_t *sdap_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
rrc_gNB_carrier_data_t *carrier,
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
NR_MAC_CellGroupConfig_t *mac_CellGroupConfig,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1921,6 +1950,10 @@ int16_t do_RRCReconfiguration(
|
||||
}
|
||||
|
||||
if(cellGroupConfig!=NULL){
|
||||
update_cellGroupConfig(cellGroupConfig,
|
||||
carrier,
|
||||
ue_context_pP->ue_context.UE_Capability_nr,
|
||||
configuration);
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
|
||||
NULL,
|
||||
(void *)cellGroupConfig,
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
* \email: raymond.knopp@eurecom.fr and navid.nikaein@eurecom.fr, kroempa@gmail.com
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __RRC_NR_MESSAGES_ASN1_MSG__H__
|
||||
#define __RRC_NR_MESSAGES_ASN1_MSG__H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
@@ -101,14 +102,19 @@ uint8_t do_RRCReject(uint8_t Mod_id,
|
||||
uint8_t *const buffer);
|
||||
|
||||
void fill_initial_SpCellConfig(int uid,
|
||||
NR_SpCellConfig_t *SpCellConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier);
|
||||
NR_SpCellConfig_t *SpCellConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
const gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
void fill_initial_cellGroupConfig(int uid,
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier);
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
const gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
rrc_gNB_carrier_data_t *carrier,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
const gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGroupConfig_t *ue_context_mastercellGroup);
|
||||
|
||||
@@ -117,7 +123,7 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
const uint8_t transaction_id,
|
||||
OCTET_STRING_t *masterCellGroup_from_DU,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
rrc_gNB_carrier_data_t *carrier);
|
||||
const gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
uint8_t do_NR_SecurityModeCommand(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
@@ -145,6 +151,9 @@ int16_t do_RRCReconfiguration(
|
||||
NR_SDAP_Config_t *sdap_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
rrc_gNB_carrier_data_t *carrier,
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
NR_MAC_CellGroupConfig_t *mac_CellGroupConfig,
|
||||
NR_CellGroupConfig_t *cellGroupConfig);
|
||||
|
||||
@@ -199,3 +208,4 @@ do_RRCReestablishmentComplete(
|
||||
uint8_t *buffer, size_t buffer_size,
|
||||
int64_t rrc_TransactionIdentifier);
|
||||
|
||||
#endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */
|
||||
|
||||
@@ -31,17 +31,64 @@
|
||||
#include "nr_rrc_config.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
|
||||
void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
int numerology,
|
||||
int rbsize,
|
||||
int mcs_table) {
|
||||
|
||||
int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
NR_BandNR_t *nr_bandnr = CALLOC(1,sizeof(NR_BandNR_t));
|
||||
nr_bandnr->bandNR = band;
|
||||
ASN_SEQUENCE_ADD(&cap->rf_Parameters.supportedBandListNR.list,
|
||||
nr_bandnr);
|
||||
if (mcs_table == 1) {
|
||||
int bw = get_supported_band_index(numerology, band, rbsize);
|
||||
if (band>256) {
|
||||
NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[0];
|
||||
bandNRinfo->pdsch_256QAM_FR2 = CALLOC(1,sizeof(*bandNRinfo->pdsch_256QAM_FR2));
|
||||
*bandNRinfo->pdsch_256QAM_FR2 = NR_BandNR__pdsch_256QAM_FR2_supported;
|
||||
}
|
||||
else{
|
||||
cap->phy_Parameters.phy_ParametersFR1 = CALLOC(1,sizeof(*cap->phy_Parameters.phy_ParametersFR1));
|
||||
NR_Phy_ParametersFR1_t *phy_fr1 = cap->phy_Parameters.phy_ParametersFR1;
|
||||
phy_fr1->pdsch_256QAM_FR1 = CALLOC(1,sizeof(*phy_fr1->pdsch_256QAM_FR1));
|
||||
*phy_fr1->pdsch_256QAM_FR1 = NR_Phy_ParametersFR1__pdsch_256QAM_FR1_supported;
|
||||
}
|
||||
cap->featureSets = CALLOC(1,sizeof(*cap->featureSets));
|
||||
NR_FeatureSets_t *fs=cap->featureSets;
|
||||
fs->featureSetsDownlinkPerCC = CALLOC(1,sizeof(*fs->featureSetsDownlinkPerCC));
|
||||
NR_FeatureSetDownlinkPerCC_t *fs_cc = CALLOC(1,sizeof(NR_FeatureSetDownlinkPerCC_t));
|
||||
fs_cc->supportedSubcarrierSpacingDL = numerology;
|
||||
if(band>256) {
|
||||
fs_cc->supportedBandwidthDL.present = NR_SupportedBandwidth_PR_fr2;
|
||||
fs_cc->supportedBandwidthDL.choice.fr2 = bw;
|
||||
}
|
||||
else{
|
||||
fs_cc->supportedBandwidthDL.present = NR_SupportedBandwidth_PR_fr1;
|
||||
fs_cc->supportedBandwidthDL.choice.fr1 = bw;
|
||||
}
|
||||
fs_cc->supportedModulationOrderDL = CALLOC(1,sizeof(*fs_cc->supportedModulationOrderDL));
|
||||
*fs_cc->supportedModulationOrderDL = NR_ModulationOrder_qam256;
|
||||
ASN_SEQUENCE_ADD(&fs->featureSetsDownlinkPerCC->list,
|
||||
fs_cc);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc){
|
||||
|
||||
lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
|
||||
int curr_bwp = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
// coreset duration setting to be improved in the framework of RRC harmonization, potentially using a common function
|
||||
int len_coreset = 1;
|
||||
if (curr_bwp < 48)
|
||||
len_coreset = 2;
|
||||
// setting default TDA for DL with
|
||||
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
|
||||
timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
|
||||
timedomainresourceallocation->startSymbolAndLength = get_SLIV(1,13); // basic slot configuration starting in symbol 1 til the end of the slot
|
||||
timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset); // basic slot configuration starting in symbol 1 til the end of the slot
|
||||
ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,
|
||||
timedomainresourceallocation);
|
||||
|
||||
if(frame_type==TDD) {
|
||||
// TDD
|
||||
if(scc->tdd_UL_DL_ConfigurationCommon) {
|
||||
@@ -49,7 +96,7 @@ void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc){
|
||||
if(dl_symb > 1) {
|
||||
timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
|
||||
timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
|
||||
timedomainresourceallocation->startSymbolAndLength = get_SLIV(1,dl_symb-1); // mixed slot configuration starting in symbol 1 til the end of the dl allocation
|
||||
timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation
|
||||
ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,
|
||||
timedomainresourceallocation);
|
||||
}
|
||||
@@ -102,6 +149,52 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){
|
||||
ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap,
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||||
NR_ServingCellConfigCommon_t *scc) {
|
||||
|
||||
if (cap == NULL){
|
||||
bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
struct NR_FrequencyInfoDL__scs_SpecificCarrierList scs_list = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList;
|
||||
int bw_rb = -1;
|
||||
for(int i=0; i<scs_list.list.count; i++){
|
||||
if(scs == scs_list.list.array[i]->subcarrierSpacing){
|
||||
bw_rb = scs_list.list.array[i]->carrierBandwidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertFatal(bw_rb>0,"Could not find scs-SpecificCarrierList element for scs %d",scs);
|
||||
int bw = get_supported_band_index(scs, band, bw_rb);
|
||||
AssertFatal(bw>0,"Supported band corresponding to %d RBs not found\n", bw_rb);
|
||||
|
||||
bool supported = false;
|
||||
if (band>256) {
|
||||
for (int i=0;i<cap->rf_Parameters.supportedBandListNR.list.count;i++) {
|
||||
NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i];
|
||||
if(bandNRinfo->bandNR == band && bandNRinfo->pdsch_256QAM_FR2) {
|
||||
supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cap->phy_Parameters.phy_ParametersFR1 && cap->phy_Parameters.phy_ParametersFR1->pdsch_256QAM_FR1)
|
||||
supported = true;
|
||||
|
||||
if (supported) {
|
||||
if(bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == NULL)
|
||||
bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table));
|
||||
*bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256;
|
||||
}
|
||||
else
|
||||
bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,14 @@ typedef struct physicalcellgroup_s{
|
||||
|
||||
void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc);
|
||||
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay);
|
||||
void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap,
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||||
NR_ServingCellConfigCommon_t *scc);
|
||||
void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
int numerology,
|
||||
int rbsize,
|
||||
int mcs_table);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -345,14 +345,18 @@ typedef struct gNB_RRC_UE_s {
|
||||
uint8_t setup_e_rabs;
|
||||
/* Number of e_rab to be setup in the list */
|
||||
uint8_t nb_of_e_rabs;
|
||||
/* Total number of pdu session already setup in the list */
|
||||
uint8_t setup_pdu_sessions;
|
||||
/* Number of pdu session to be setup in the list */
|
||||
uint8_t nb_of_pdusessions;
|
||||
/* Number of e_rab to be modified in the list */
|
||||
uint8_t nb_of_modify_e_rabs;
|
||||
uint8_t nb_of_failed_e_rabs;
|
||||
e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
|
||||
/* Total number of pdu session already setup in the list */
|
||||
uint8_t setup_pdu_sessions;
|
||||
/* Number of pdu session to be setup in the list */
|
||||
uint8_t nb_of_pdusessions;
|
||||
/* Number of e_rab to be modified in the list */
|
||||
uint8_t nb_of_modify_pdusessions;
|
||||
uint8_t nb_of_failed_pdusessions;
|
||||
pdu_session_param_t modify_pdusession[NR_NB_RB_MAX];
|
||||
/* list of e_rab to be setup by RRC layers */
|
||||
/* list of pdu session to be setup by RRC layers */
|
||||
e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
|
||||
@@ -420,12 +424,6 @@ typedef struct rrc_gNB_ue_context_s {
|
||||
struct gNB_RRC_UE_s ue_context;
|
||||
} rrc_gNB_ue_context_t;
|
||||
|
||||
typedef struct {
|
||||
int N1;
|
||||
int N2;
|
||||
int XP;
|
||||
} rrc_pdsch_AntennaPorts_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
// buffer that contains the encoded messages
|
||||
@@ -450,13 +448,6 @@ typedef struct {
|
||||
NR_SIB2_t *sib2;
|
||||
NR_SIB3_t *sib3;
|
||||
NR_BCCH_DL_SCH_Message_t systemInformation; // SIB23
|
||||
int ssb_SubcarrierOffset;
|
||||
int sib1_tda;
|
||||
rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
||||
int pusch_AntennaPorts;
|
||||
int minRXTXTIME;
|
||||
int do_CSIRS;
|
||||
int do_SRS;
|
||||
NR_BCCH_DL_SCH_Message_t *siblock1;
|
||||
NR_ServingCellConfigCommon_t *servingcellconfigcommon;
|
||||
NR_PDCCH_ConfigSIB1_t *pdcch_ConfigSIB1;
|
||||
|
||||
@@ -76,12 +76,10 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti);
|
||||
void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
rrc_pdsch_AntennaPorts_t dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int do_srs,
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
int uid);
|
||||
|
||||
void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
@@ -94,10 +92,8 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
rrc_pdsch_AntennaPorts_t dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int do_srs,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
int uid);
|
||||
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
|
||||
@@ -208,3 +204,24 @@ void
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *ue_context_pP);
|
||||
|
||||
rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const NR_SRB_ToAddModList_t * const srb2add_listP,
|
||||
const NR_DRB_ToAddModList_t * const drb2add_listP,
|
||||
const NR_DRB_ToReleaseList_t * const drb2release_listP,
|
||||
const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
NR_SRB_ToAddModList_t *const srb2add_list,
|
||||
NR_DRB_ToAddModList_t *const drb2add_list,
|
||||
NR_DRB_ToReleaseList_t *const drb2release_list,
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
,rb_id_t *const defaultDRB,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
+260
-110
@@ -98,6 +98,7 @@
|
||||
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
|
||||
#include <openair2/X2AP/x2ap_eNB.h>
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include <openair2/RRC/NR/nr_rrc_proto.h>
|
||||
|
||||
#include "BIT_STRING.h"
|
||||
#include "assertions.h"
|
||||
@@ -165,17 +166,16 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
|
||||
|
||||
if (NODE_IS_MONOLITHIC(rrc->node_type)){
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->carrier.ssb_SubcarrierOffset,
|
||||
rrc->carrier.pdsch_AntennaPorts,
|
||||
rrc->carrier.pusch_AntennaPorts,
|
||||
rrc->carrier.sib1_tda,
|
||||
rrc->carrier.minRXTXTIME,
|
||||
(NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon,
|
||||
&rrc->carrier.mib,
|
||||
0,
|
||||
0, // WIP hardcoded rnti
|
||||
(NR_CellGroupConfig_t *)NULL
|
||||
);
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
rrc->carrier.servingcellconfigcommon,
|
||||
&rrc->carrier.mib,
|
||||
0,
|
||||
0, // WIP hardcoded rnti
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* set flag to indicate that cell information is configured. This is required
|
||||
@@ -215,16 +215,8 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
|
||||
rrc->s1ap_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
|
||||
rrc->initial_id2_ngap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
|
||||
rrc->ngap_id2_ngap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
|
||||
rrc->configuration = *configuration;
|
||||
rrc->carrier.servingcellconfigcommon = configuration->scc;
|
||||
rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset;
|
||||
rrc->carrier.pdsch_AntennaPorts.N1 = configuration->pdsch_AntennaPorts_N1;
|
||||
rrc->carrier.pdsch_AntennaPorts.N2 = configuration->pdsch_AntennaPorts_N2;
|
||||
rrc->carrier.pdsch_AntennaPorts.XP = configuration->pdsch_AntennaPorts_XP;
|
||||
rrc->carrier.pusch_AntennaPorts = configuration->pusch_AntennaPorts;
|
||||
rrc->carrier.minRXTXTIME = configuration->minRXTXTIME;
|
||||
rrc->carrier.sib1_tda = configuration->sib1_tda;
|
||||
rrc->carrier.do_CSIRS = configuration->do_CSIRS;
|
||||
rrc->carrier.do_SRS = configuration->do_SRS;
|
||||
nr_rrc_config_ul_tda(configuration->scc,configuration->minRXTXTIME);
|
||||
/// System Information INIT
|
||||
pthread_mutex_init(&rrc->cell_info_mutex,NULL);
|
||||
@@ -280,24 +272,25 @@ void apply_macrlc_config(gNB_RRC_INST *rrc,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
const protocol_ctxt_t *const ctxt_pP ) {
|
||||
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->carrier.ssb_SubcarrierOffset,
|
||||
rrc->carrier.pdsch_AntennaPorts,
|
||||
rrc->carrier.pusch_AntennaPorts,
|
||||
rrc->carrier.sib1_tda,
|
||||
rrc->carrier.minRXTXTIME,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
ue_context_pP->ue_context.rnti,
|
||||
get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup : (NR_CellGroupConfig_t *)NULL);
|
||||
NR_CellGroupConfig_t *cgc = get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup : NULL;
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
ue_context_pP->ue_context.rnti,
|
||||
cgc);
|
||||
|
||||
nr_rrc_rlc_config_asn1_req(ctxt_pP,
|
||||
ue_context_pP->ue_context.SRB_configList,
|
||||
ue_context_pP->ue_context.DRB_configList,
|
||||
NULL,
|
||||
NULL,
|
||||
get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL);
|
||||
nr_rrc_rlc_config_asn1_req(ctxt_pP,
|
||||
ue_context_pP->ue_context.SRB_configList,
|
||||
ue_context_pP->ue_context.DRB_configList,
|
||||
NULL,
|
||||
NULL,
|
||||
get_softmodem_params()->sa ? cgc->rlc_BearerToAddModList : NULL);
|
||||
|
||||
}
|
||||
|
||||
@@ -341,10 +334,11 @@ rrc_gNB_generate_RRCSetup(
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ue_context_pP,
|
||||
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
|
||||
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
|
||||
masterCellGroup_from_DU,
|
||||
scc,&rrc->carrier);
|
||||
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
|
||||
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
|
||||
masterCellGroup_from_DU,
|
||||
scc,
|
||||
&rrc->configuration);
|
||||
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC,
|
||||
(char *)(ue_p->Srb0.Tx_buffer.Payload),
|
||||
@@ -451,10 +445,11 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(
|
||||
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ue_context_pP,
|
||||
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
|
||||
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
|
||||
NULL,
|
||||
scc,&rrc_instance_p->carrier);
|
||||
(uint8_t *) ue_p->Srb0.Tx_buffer.Payload,
|
||||
rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id),
|
||||
NULL,
|
||||
scc,
|
||||
&rrc_instance_p->configuration);
|
||||
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC,
|
||||
(char *)(ue_p->Srb0.Tx_buffer.Payload),
|
||||
@@ -466,17 +461,16 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(
|
||||
PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP));
|
||||
|
||||
rrc_mac_config_req_gNB(rrc_instance_p->module_id,
|
||||
rrc_instance_p->carrier.ssb_SubcarrierOffset,
|
||||
rrc_instance_p->carrier.pdsch_AntennaPorts,
|
||||
rrc_instance_p->carrier.pusch_AntennaPorts,
|
||||
rrc_instance_p->carrier.sib1_tda,
|
||||
rrc_instance_p->carrier.minRXTXTIME,
|
||||
(NR_ServingCellConfigCommon_t *)rrc_instance_p->carrier.servingcellconfigcommon,
|
||||
rrc_instance_p->configuration.ssb_SubcarrierOffset,
|
||||
rrc_instance_p->configuration.pdsch_AntennaPorts,
|
||||
rrc_instance_p->configuration.pusch_AntennaPorts,
|
||||
rrc_instance_p->configuration.sib1_tda,
|
||||
rrc_instance_p->configuration.minRXTXTIME,
|
||||
rrc_instance_p->carrier.servingcellconfigcommon,
|
||||
&rrc_instance_p->carrier.mib,
|
||||
0,
|
||||
ue_context_pP->ue_context.rnti,
|
||||
(NR_CellGroupConfig_t *)NULL
|
||||
);
|
||||
NULL);
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n",
|
||||
@@ -710,6 +704,8 @@ rrc_gNB_generate_defaultRRCReconfiguration(
|
||||
dedicatedNAS_MessageList = NULL;
|
||||
}
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer),
|
||||
xid,
|
||||
@@ -720,8 +716,11 @@ rrc_gNB_generate_defaultRRCReconfiguration(
|
||||
NULL,
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
ue_context_pP,
|
||||
&rrc->carrier,
|
||||
&rrc->configuration,
|
||||
NULL,
|
||||
NULL);
|
||||
ue_p->masterCellGroup);
|
||||
|
||||
free(ue_context_pP->ue_context.nas_pdu.buffer);
|
||||
|
||||
@@ -981,6 +980,9 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
NULL,
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
ue_context_pP,
|
||||
&rrc->carrier,
|
||||
&rrc->configuration,
|
||||
NULL,
|
||||
cellGroupConfig);
|
||||
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n");
|
||||
@@ -1023,6 +1025,179 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rrc_gNB_modify_dedicatedRRCReconfiguration(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *ue_context_pP)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
NR_DRB_ToAddMod_t *DRB_config = NULL;
|
||||
NR_DRB_ToAddModList_t **DRB_configList = NULL;
|
||||
NR_DRB_ToAddModList_t *DRB_configList2 = NULL;
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList
|
||||
*dedicatedNAS_MessageList = NULL;
|
||||
NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL;
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint16_t size;
|
||||
int qos_flow_index = 0;
|
||||
int i, j;
|
||||
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
|
||||
DRB_configList = &ue_context_pP->ue_context.DRB_configList;
|
||||
|
||||
DRB_configList2 = CALLOC(1, sizeof(NR_DRB_ToAddModList_t));
|
||||
memset(DRB_configList2, 0, sizeof(NR_DRB_ToAddModList_t));
|
||||
|
||||
dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList));
|
||||
|
||||
for (i = 0; i < ue_context_pP->ue_context.nb_of_modify_pdusessions; i++) {
|
||||
// bypass the new and already configured pdu sessions
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].status >= PDU_SESSION_STATUS_DONE) {
|
||||
ue_context_pP->ue_context.modify_pdusession[i].xid = xid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].cause != NGAP_CAUSE_NOTHING) {
|
||||
// set xid of failure pdu session
|
||||
ue_context_pP->ue_context.modify_pdusession[i].xid = xid;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
// search exist DRB_config
|
||||
for (j = 0; j < (*DRB_configList)->list.count; j++) {
|
||||
if ((*DRB_configList)->list.array[j]->cnAssociation->choice.sdap_Config->pdu_Session ==
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id) {
|
||||
DRB_config = (*DRB_configList)->list.array[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (DRB_config == NULL) {
|
||||
ue_context_pP->ue_context.modify_pdusession[i].xid = xid;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_unspecified;
|
||||
ue_context_pP->ue_context.nb_of_failed_pdusessions++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
|
||||
for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.modify_pdusession[i].param.nb_qos; qos_flow_index++) {
|
||||
switch (ue_context_pP->ue_context.modify_pdusession[i].param.qos[qos_flow_index].fiveQI) {
|
||||
case 1: //100ms
|
||||
case 2: //150ms
|
||||
case 3: //50ms
|
||||
case 4: //300ms
|
||||
case 5: //100ms
|
||||
case 6: //300ms
|
||||
case 7: //100ms
|
||||
case 8: //300ms
|
||||
case 9: //300ms Video (Buffered Streaming)TCP-based (e.g., www, e-mail, chat, ftp, p2p file sharing, progressive video, etc.)
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC,"not supported 5qi %lu\n", ue_context_pP->ue_context.modify_pdusession[i].param.qos[qos_flow_index].fiveQI);
|
||||
ue_context_pP->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].xid = xid;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_not_supported_5QI_value;
|
||||
ue_context_pP->ue_context.nb_of_failed_pdusessions++;
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC, "PDU SESSION ID %ld, DRB ID %ld (index %d), QOS flow %d, 5QI %ld \n",
|
||||
DRB_config->cnAssociation->choice.sdap_Config->pdu_Session,
|
||||
DRB_config->drb_Identity, i,
|
||||
qos_flow_index,
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.qos[qos_flow_index].fiveQI
|
||||
);
|
||||
}
|
||||
|
||||
ASN_SEQUENCE_ADD(&DRB_configList2->list, DRB_config);
|
||||
|
||||
ue_context_pP->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_DONE;
|
||||
ue_context_pP->ue_context.modify_pdusession[i].xid = xid;
|
||||
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.buffer != NULL) {
|
||||
dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t));
|
||||
memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t));
|
||||
OCTET_STRING_fromBuf(dedicatedNAS_Message,
|
||||
(char *)ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.buffer,
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.length);
|
||||
ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message);
|
||||
|
||||
LOG_I(NR_RRC,"add NAS info with size %d (pdusession id %d)\n",ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length,
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id);
|
||||
} else {
|
||||
// TODO
|
||||
LOG_E(NR_RRC,"no NAS info (pdusession id %d)\n", ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
if (dedicatedNAS_MessageList->list.count == 0) {
|
||||
free(dedicatedNAS_MessageList);
|
||||
dedicatedNAS_MessageList = NULL;
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer),
|
||||
xid,
|
||||
NULL,
|
||||
DRB_configList2,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n");
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
for (i = 0; i < ue_context_pP->ue_context.nb_of_modify_pdusessions; i++) {
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.buffer != NULL) {
|
||||
/* Free the NAS PDU buffer and invalidate it */
|
||||
free(ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.buffer);
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.nas_pdu.buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
"[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n",
|
||||
ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti);
|
||||
LOG_D(NR_RRC,
|
||||
"[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n",
|
||||
ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH);
|
||||
|
||||
#ifdef ITTI_SIM
|
||||
MessageDef *message_p;
|
||||
uint8_t *message_buffer;
|
||||
message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, size);
|
||||
memcpy (message_buffer, buffer, size);
|
||||
message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, GNB_RRC_DCCH_DATA_IND);
|
||||
GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH;
|
||||
GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer;
|
||||
GNB_RRC_DCCH_DATA_IND (message_p).size = size;
|
||||
itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p);
|
||||
#else
|
||||
nr_rrc_data_req(
|
||||
ctxt_pP,
|
||||
DCCH,
|
||||
rrc_gNB_mui++,
|
||||
SDU_CONFIRM_NO,
|
||||
size,
|
||||
buffer,
|
||||
PDCP_TRANSMISSION_MODE_CONTROL);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
@@ -1080,6 +1255,9 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
ue_context_pP->ue_context.pdu_session_release_command_flag = 1;
|
||||
@@ -1183,17 +1361,16 @@ rrc_gNB_process_RRCReconfigurationComplete(
|
||||
|
||||
if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) {
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->carrier.ssb_SubcarrierOffset,
|
||||
rrc->carrier.pdsch_AntennaPorts,
|
||||
rrc->carrier.pusch_AntennaPorts,
|
||||
rrc->carrier.sib1_tda,
|
||||
rrc->carrier.minRXTXTIME,
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
ue_context_pP->ue_context.rnti,
|
||||
ue_context_pP->ue_context.masterCellGroup
|
||||
);
|
||||
ue_context_pP->ue_context.masterCellGroup);
|
||||
LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti);
|
||||
nr_rrc_rlc_config_asn1_req(ctxt_pP,
|
||||
SRB_configList, // NULL,
|
||||
@@ -1629,6 +1806,9 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete(
|
||||
NULL, // MeasObj_list,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,
|
||||
"[MSG] RRC Reconfiguration\n");
|
||||
@@ -2190,10 +2370,23 @@ rrc_gNB_decode_dcch(
|
||||
//NGAP_PDUSESSION_RELEASE_RESPONSE
|
||||
rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid);
|
||||
} else if (ue_context_p->ue_context.established_pdu_sessions_flag != 1) {
|
||||
if (ue_context_p->ue_context.setup_pdu_sessions > 0) {
|
||||
if (ue_context_p->ue_context.nb_of_pdusessions > 0) {
|
||||
rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP,
|
||||
ue_context_p,
|
||||
ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier);
|
||||
ue_context_p->ue_context.nb_of_pdusessions = 0;
|
||||
}
|
||||
}
|
||||
if (ue_context_p->ue_context.nb_of_modify_pdusessions > 0) {
|
||||
rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(ctxt_pP,
|
||||
ue_context_p,
|
||||
ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier);
|
||||
ue_context_p->ue_context.nb_of_modify_pdusessions = 0;
|
||||
ue_context_p->ue_context.nb_of_failed_pdusessions = 0;
|
||||
memset(ue_context_p->ue_context.modify_pdusession, 0, sizeof(ue_context_p->ue_context.modify_pdusession));
|
||||
|
||||
for(int i = 0; i < NR_NB_RB_MAX; i++) {
|
||||
ue_context_p->ue_context.modify_pdusession[i].xid = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3158,51 +3351,6 @@ unsigned int get_ul_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
int is_dl_256QAM_supported(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) {
|
||||
int common_band = *rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
if (common_band>256) {
|
||||
for (int i=0;i<cap->rf_Parameters.supportedBandListNR.list.count;i++) {
|
||||
NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i];
|
||||
if (bandNRinfo->bandNR == common_band && !bandNRinfo->pdsch_256QAM_FR2) return (0);
|
||||
}
|
||||
}
|
||||
else if (cap->phy_Parameters.phy_ParametersFR1 && !cap->phy_Parameters.phy_ParametersFR1->pdsch_256QAM_FR1) return(0);
|
||||
|
||||
// check featureSet
|
||||
NR_FeatureSets_t *fs=cap->featureSets;
|
||||
if (fs) {
|
||||
// go through DL feature sets and look for one with current SCS
|
||||
for (int i=0;i<fs->featureSetsDownlinkPerCC->list.count;i++) {
|
||||
if (fs->featureSetsDownlinkPerCC->list.array[i]->supportedSubcarrierSpacingDL == common_scs &&
|
||||
fs->featureSetsDownlinkPerCC->list.array[i]->supportedModulationOrderDL &&
|
||||
*fs->featureSetsDownlinkPerCC->list.array[i]->supportedModulationOrderDL == NR_ModulationOrder_qam256) return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int is_ul_256QAM_supported(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) {
|
||||
int common_band = *rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0];
|
||||
int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
for (int i=0;i<cap->rf_Parameters.supportedBandListNR.list.count;i++) {
|
||||
NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i];
|
||||
if (bandNRinfo->bandNR == common_band && !bandNRinfo->pusch_256QAM) return (0);
|
||||
}
|
||||
|
||||
// check featureSet
|
||||
NR_FeatureSets_t *fs=cap->featureSets;
|
||||
if (fs) {
|
||||
// go through UL feature sets and look for one with current SCS
|
||||
for (int i=0;i<fs->featureSetsUplinkPerCC->list.count;i++) {
|
||||
if (fs->featureSetsUplinkPerCC->list.array[i]->supportedSubcarrierSpacingUL == common_scs &&
|
||||
fs->featureSetsUplinkPerCC->list.array[i]->supportedModulationOrderUL &&
|
||||
*fs->featureSetsUplinkPerCC->list.array[i]->supportedModulationOrderUL == NR_ModulationOrder_qam256) return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int get_ul_mimo_layersCB(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) {
|
||||
int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
@@ -3272,11 +3420,9 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
|
||||
}
|
||||
|
||||
if (ue_context_p->ue_context.UE_Capability_nr) {
|
||||
fprintf(fd,"NR RRC UE cap: BW DL %x. BW UL %x, 256 QAM DL %s, 256 QAM UL %s, DL MIMO Layers %d UL MIMO Layers (CB) %d UL MIMO Layers (nonCB) %d\n",
|
||||
fprintf(fd,"NR RRC UE cap: BW DL %x. BW UL %x, DL MIMO Layers %d UL MIMO Layers (CB) %d UL MIMO Layers (nonCB) %d\n",
|
||||
get_dl_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr),
|
||||
get_ul_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr),
|
||||
is_dl_256QAM_supported(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr) == 1 ? "yes" : "no",
|
||||
is_ul_256QAM_supported(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr) == 1 ? "yes" : "no",
|
||||
get_dl_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr),
|
||||
get_ul_mimo_layersCB(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr),
|
||||
get_ul_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr));
|
||||
@@ -3471,6 +3617,10 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, msg_name_p, instance);
|
||||
break;
|
||||
|
||||
case NGAP_PDUSESSION_MODIFY_REQ:
|
||||
rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(msg_p, msg_name_p, instance);
|
||||
break;
|
||||
|
||||
case NGAP_PDUSESSION_RELEASE_COMMAND:
|
||||
rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, msg_name_p, instance);
|
||||
break;
|
||||
|
||||
+272
-17
@@ -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)) {
|
||||
@@ -1058,6 +1055,264 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int
|
||||
rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(
|
||||
MessageDef *msg_p,
|
||||
const char *msg_name,
|
||||
instance_t instance
|
||||
)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
uint16_t ue_initial_id;
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
uint8_t nb_pdusessions_tomodify;
|
||||
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
||||
uint8_t i;
|
||||
uint8_t qos_flow_index;
|
||||
protocol_ctxt_t ctxt;
|
||||
|
||||
ue_initial_id = NGAP_PDUSESSION_MODIFY_REQ(msg_p).ue_initial_id;
|
||||
gNB_ue_ngap_id = NGAP_PDUSESSION_MODIFY_REQ(msg_p).gNB_ue_ngap_id;
|
||||
nb_pdusessions_tomodify = NGAP_PDUSESSION_MODIFY_REQ(msg_p).nb_pdusessions_tomodify;
|
||||
|
||||
ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_MODIFY_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id);
|
||||
// TODO
|
||||
return (-1);
|
||||
} else {
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
|
||||
ctxt.eNB_index = 0;
|
||||
|
||||
ue_context_p->ue_context.gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||
{
|
||||
int j;
|
||||
boolean_t is_treated[NGAP_MAX_PDUSESSION] = {FALSE};
|
||||
uint8_t nb_of_failed_pdusessions = 0;
|
||||
|
||||
for (i = 0; i < nb_pdusessions_tomodify; i++) {
|
||||
if (is_treated[i] == TRUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Check if same PDU session ID to handle multiple pdu sessions
|
||||
for (j = i+1; j < nb_pdusessions_tomodify; j++) {
|
||||
if (is_treated[j] == FALSE &&
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[j].pdusession_id ==
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id) {
|
||||
// handle multiple pdu session id
|
||||
LOG_D(NR_RRC, "handle multiple pdu session id \n");
|
||||
ue_context_p->ue_context.modify_pdusession[j].status = PDU_SESSION_STATUS_NEW;
|
||||
ue_context_p->ue_context.modify_pdusession[j].param.pdusession_id =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[j].pdusession_id;
|
||||
ue_context_p->ue_context.modify_pdusession[j].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
ue_context_p->ue_context.modify_pdusession[j].cause_value = NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances;
|
||||
nb_of_failed_pdusessions++;
|
||||
is_treated[i] = TRUE;
|
||||
is_treated[j] = TRUE;
|
||||
}
|
||||
}
|
||||
// handle multiple pdu session id case
|
||||
if (is_treated[i] == TRUE) {
|
||||
LOG_D(NR_RRC, "handle multiple pdu session id \n");
|
||||
ue_context_p->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_NEW;
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.pdusession_id =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id;
|
||||
ue_context_p->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
ue_context_p->ue_context.modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances;
|
||||
nb_of_failed_pdusessions++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check pdu session ID is established
|
||||
for (j = 0; j < NR_NB_RB_MAX -3; j++) {
|
||||
if (ue_context_p->ue_context.pduSession[j].param.pdusession_id ==
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id) {
|
||||
if (ue_context_p->ue_context.pduSession[j].status == PDU_SESSION_STATUS_TORELEASE ||
|
||||
ue_context_p->ue_context.pduSession[j].status == PDU_SESSION_STATUS_DONE) {
|
||||
break;
|
||||
}
|
||||
// Found established pdu session, prepare to send RRC message
|
||||
ue_context_p->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_NEW;
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.pdusession_id =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id;
|
||||
ue_context_p->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_NOTHING;
|
||||
if (NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].nas_pdu.buffer != NULL) {
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.nas_pdu.buffer =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].nas_pdu.buffer;
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.nas_pdu.length =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].nas_pdu.length;
|
||||
}
|
||||
// Save new pdu session parameters, qos, upf addr, teid
|
||||
for (qos_flow_index = 0; qos_flow_index < NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].nb_qos; qos_flow_index++) {
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.qos[qos_flow_index] =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].qos[qos_flow_index];
|
||||
}
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.nb_qos =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].nb_qos;
|
||||
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.upf_addr =
|
||||
ue_context_p->ue_context.pduSession[j].param.upf_addr;
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.gtp_teid =
|
||||
ue_context_p->ue_context.pduSession[j].param.gtp_teid;
|
||||
|
||||
is_treated[i] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// handle Unknown pdu session ID
|
||||
if (is_treated[i] == FALSE) {
|
||||
LOG_D(NR_RRC, "handle Unknown pdu session ID \n");
|
||||
ue_context_p->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_NEW;
|
||||
ue_context_p->ue_context.modify_pdusession[i].param.pdusession_id =
|
||||
NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id;
|
||||
ue_context_p->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
ue_context_p->ue_context.modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
|
||||
nb_of_failed_pdusessions++;
|
||||
is_treated[i] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ue_context_p->ue_context.nb_of_modify_pdusessions = nb_pdusessions_tomodify;
|
||||
ue_context_p->ue_context.nb_of_failed_pdusessions = nb_of_failed_pdusessions;
|
||||
}
|
||||
|
||||
if (ue_context_p->ue_context.nb_of_failed_pdusessions < ue_context_p->ue_context.nb_of_modify_pdusessions) {
|
||||
LOG_D(NR_RRC, "generate RRCReconfiguration \n");
|
||||
rrc_gNB_modify_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
|
||||
} else { // all pdu modification failed
|
||||
LOG_I(NR_RRC, "pdu session modify failed, fill NGAP_PDUSESSION_MODIFY_RESP with the pdu session information that failed to modify \n");
|
||||
uint8_t nb_of_pdu_sessions_failed = 0;
|
||||
MessageDef *msg_fail_p = NULL;
|
||||
msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP);
|
||||
if (msg_fail_p == NULL) {
|
||||
LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_fail_p is NULL \n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).nb_of_pdusessions = 0;
|
||||
|
||||
for (nb_of_pdu_sessions_failed = 0; nb_of_pdu_sessions_failed < ue_context_p->ue_context.nb_of_failed_pdusessions; nb_of_pdu_sessions_failed++) {
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).pdusessions_failed[nb_of_pdu_sessions_failed].pdusession_id =
|
||||
ue_context_p->ue_context.modify_pdusession[nb_of_pdu_sessions_failed].param.pdusession_id;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).pdusessions_failed[nb_of_pdu_sessions_failed].cause =
|
||||
ue_context_p->ue_context.modify_pdusession[nb_of_pdu_sessions_failed].cause;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).pdusessions_failed[nb_of_pdu_sessions_failed].cause_value =
|
||||
ue_context_p->ue_context.modify_pdusession[nb_of_pdu_sessions_failed].cause_value;
|
||||
}
|
||||
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_fail_p).nb_of_pdusessions_failed =
|
||||
ue_context_p->ue_context.nb_of_failed_pdusessions;
|
||||
itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
|
||||
ue_context_p->ue_context.nb_of_modify_pdusessions = 0;
|
||||
ue_context_p->ue_context.nb_of_failed_pdusessions = 0;
|
||||
memset(ue_context_p->ue_context.modify_pdusession, 0, sizeof(ue_context_p->ue_context.modify_pdusession));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int
|
||||
rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
uint8_t xid
|
||||
)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
MessageDef *msg_p = NULL;
|
||||
int i, j;
|
||||
uint8_t qos_flow_index;
|
||||
uint8_t pdu_sessions_failed = 0;
|
||||
uint8_t pdu_sessions_done = 0;
|
||||
|
||||
msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP);
|
||||
if (msg_p == NULL) {
|
||||
LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_p is NULL \n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC, "send message NGAP_PDUSESSION_MODIFY_RESP \n");
|
||||
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id;
|
||||
|
||||
for (i = 0; i < ue_context_pP->ue_context.nb_of_modify_pdusessions; i++) {
|
||||
if (xid == ue_context_pP->ue_context.modify_pdusession[i].xid) {
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].status == PDU_SESSION_STATUS_DONE) {
|
||||
for (j = 0; j < ue_context_pP->ue_context.setup_pdu_sessions; j++) {
|
||||
if (ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id ==
|
||||
ue_context_pP->ue_context.pduSession[j].param.pdusession_id) {
|
||||
LOG_I(NR_RRC, "update pdu session %d \n", ue_context_pP->ue_context.pduSession[j].param.pdusession_id);
|
||||
// Update ue_context_pP->ue_context.pduSession
|
||||
ue_context_pP->ue_context.pduSession[j].status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
ue_context_pP->ue_context.pduSession[j].cause = NGAP_CAUSE_NOTHING;
|
||||
for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.modify_pdusession[i].param.nb_qos; qos_flow_index++) {
|
||||
ue_context_pP->ue_context.pduSession[j].param.qos[qos_flow_index] =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.qos[qos_flow_index];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < ue_context_pP->ue_context.setup_pdu_sessions) {
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions[pdu_sessions_done].pdusession_id =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id;
|
||||
for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.modify_pdusession[i].param.nb_qos; qos_flow_index++) {
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.qos[qos_flow_index].qfi;
|
||||
}
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions[pdu_sessions_done].nb_of_qos_flow =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.nb_qos;
|
||||
LOG_I(NR_RRC, "Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_modify_pdusessions %d, pdusession_id %d \n ",
|
||||
pdu_sessions_done, i, ue_context_pP->ue_context.modify_pdusession[i].status, xid,
|
||||
ue_context_pP->ue_context.nb_of_modify_pdusessions,
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions[pdu_sessions_done].pdusession_id);
|
||||
pdu_sessions_done++;
|
||||
} else {
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].pdusession_id =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
|
||||
pdu_sessions_failed++;
|
||||
}
|
||||
} else if ((ue_context_pP->ue_context.modify_pdusession[i].status == PDU_SESSION_STATUS_NEW) ||
|
||||
(ue_context_pP->ue_context.modify_pdusession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) {
|
||||
LOG_D (NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n");
|
||||
} else if (ue_context_pP->ue_context.modify_pdusession[i].status == PDU_SESSION_STATUS_FAILED) {
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].pdusession_id =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].param.pdusession_id;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].cause =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).pdusessions_failed[pdu_sessions_failed].cause_value =
|
||||
ue_context_pP->ue_context.modify_pdusession[i].cause_value;
|
||||
pdu_sessions_failed++;
|
||||
}
|
||||
} else {
|
||||
LOG_D(NR_RRC,"xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ",
|
||||
i, ue_context_pP->ue_context.modify_pdusession[i].status, xid, ue_context_pP->ue_context.modify_pdusession[i].xid);
|
||||
}
|
||||
}
|
||||
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).nb_of_pdusessions = pdu_sessions_done;
|
||||
NGAP_PDUSESSION_MODIFY_RESP(msg_p).nb_of_pdusessions_failed = pdu_sessions_failed;
|
||||
|
||||
if (pdu_sessions_done > 0 || pdu_sessions_failed > 0) {
|
||||
LOG_D(NR_RRC,"NGAP_PDUSESSION_MODIFY_RESP: sending the message: nb_of_pdusessions %d, total pdu session %d, index %d\n",
|
||||
ue_context_pP->ue_context.nb_of_modify_pdusessions, ue_context_pP->ue_context.setup_pdu_sessions, i);
|
||||
itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p);
|
||||
} else {
|
||||
itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(
|
||||
const module_id_t gnb_mod_idP,
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "NR_RRCSetupComplete-IEs.h"
|
||||
#include "NR_RegisteredAMF.h"
|
||||
#include "NR_UL-DCCH-Message.h"
|
||||
#include "NGAP_CauseRadioNetwork.h"
|
||||
|
||||
typedef struct rrc_ue_ngap_ids_s {
|
||||
/* Tree related data */
|
||||
@@ -107,6 +108,27 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
|
||||
instance_t instance
|
||||
);
|
||||
|
||||
int
|
||||
rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(
|
||||
MessageDef *msg_p,
|
||||
const char *msg_name,
|
||||
instance_t instance
|
||||
);
|
||||
|
||||
int
|
||||
rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
uint8_t xid
|
||||
);
|
||||
|
||||
void
|
||||
rrc_gNB_modify_dedicatedRRCReconfiguration(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *ue_context_pP
|
||||
);
|
||||
|
||||
|
||||
void
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(
|
||||
const module_id_t gnb_mod_idP,
|
||||
|
||||
@@ -42,27 +42,7 @@
|
||||
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "UTIL/OSA/osa_defs.h"
|
||||
|
||||
extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
NR_SRB_ToAddModList_t *const srb2add_list,
|
||||
NR_DRB_ToAddModList_t *const drb2add_list,
|
||||
NR_DRB_ToReleaseList_t *const drb2release_list,
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
,rb_id_t *const defaultDRB,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const NR_SRB_ToAddModList_t * const srb2add_listP,
|
||||
const NR_DRB_ToAddModList_t * const drb2add_listP,
|
||||
const NR_DRB_ToReleaseList_t * const drb2release_listP,
|
||||
const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
#include <openair2/RRC/NR/nr_rrc_proto.h>
|
||||
|
||||
void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) {
|
||||
struct rrc_gNB_ue_context_s *ue_context_p = NULL;
|
||||
@@ -136,6 +116,7 @@ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
|
||||
void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m) {
|
||||
// generate nr-Config-r15 containers for LTE RRC : inside message for X2 EN-DC (CG-Config Message from 38.331)
|
||||
rrc_gNB_carrier_data_t *carrier=&rrc->carrier;
|
||||
const gNB_RrcConfigurationReq *configuration = &rrc->configuration;
|
||||
MessageDef *msg;
|
||||
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK);
|
||||
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
|
||||
@@ -260,27 +241,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
cipher_algo,
|
||||
NR_SecurityConfig__keyToUse_secondary);
|
||||
}
|
||||
if (ue_context_p->ue_context.spCellConfig) {
|
||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||
ue_context_p->ue_context.spCellConfig->spCellConfigDedicated,
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
carrier->pdsch_AntennaPorts,
|
||||
carrier->minRXTXTIME,
|
||||
carrier->do_CSIRS,
|
||||
carrier->do_SRS,
|
||||
ue_context_p->local_uid);
|
||||
} else {
|
||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||
NULL,
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
carrier->pdsch_AntennaPorts,
|
||||
carrier->minRXTXTIME,
|
||||
carrier->do_CSIRS,
|
||||
carrier->do_SRS,
|
||||
ue_context_p->local_uid);
|
||||
}
|
||||
NR_ServingCellConfig_t *scc = ue_context_p->ue_context.spCellConfig
|
||||
? ue_context_p->ue_context.spCellConfig->spCellConfigDedicated
|
||||
: NULL;
|
||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||
scc,
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
ue_context_p->ue_context.UE_Capability_nr,
|
||||
configuration,
|
||||
ue_context_p->local_uid);
|
||||
ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
|
||||
memset((void *)CG_Config,0,sizeof(*CG_Config));
|
||||
@@ -377,11 +347,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
// configure MAC and RLC
|
||||
if (NODE_IS_DU(rrc->node_type)) {
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->carrier.ssb_SubcarrierOffset,
|
||||
rrc->carrier.pdsch_AntennaPorts,
|
||||
rrc->carrier.pusch_AntennaPorts,
|
||||
rrc->carrier.sib1_tda,
|
||||
rrc->carrier.minRXTXTIME,
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
rrc->carrier.servingcellconfigcommon,
|
||||
&rrc->carrier.mib,
|
||||
1, // add_ue flag
|
||||
@@ -389,11 +359,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
ue_context_p->ue_context.secondaryCellGroup);
|
||||
} else {
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
rrc->carrier.ssb_SubcarrierOffset,
|
||||
rrc->carrier.pdsch_AntennaPorts,
|
||||
rrc->carrier.pusch_AntennaPorts,
|
||||
rrc->carrier.sib1_tda,
|
||||
rrc->carrier.minRXTXTIME,
|
||||
rrc->configuration.ssb_SubcarrierOffset,
|
||||
rrc->configuration.pdsch_AntennaPorts,
|
||||
rrc->configuration.pusch_AntennaPorts,
|
||||
rrc->configuration.sib1_tda,
|
||||
rrc->configuration.minRXTXTIME,
|
||||
NULL,
|
||||
NULL,
|
||||
1, // add_ue flag
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "SIMULATION/TOOLS/sim.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "nr_rrc_config.h"
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
@@ -52,24 +53,27 @@
|
||||
void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
rrc_pdsch_AntennaPorts_t dl_antenna_ports_struct,
|
||||
int minRXTXTIME,
|
||||
int do_csirs,
|
||||
int do_srs,
|
||||
int uid) {
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
int uid)
|
||||
{
|
||||
const rrc_pdsch_AntennaPorts_t* pdschap = &configuration->pdsch_AntennaPorts;
|
||||
const int dl_antenna_ports = pdschap->N1 * pdschap->N2 * pdschap->XP;
|
||||
const int do_csirs = configuration->do_CSIRS;
|
||||
|
||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
||||
|
||||
if(uecap == NULL)
|
||||
LOG_E(RRC,"No UE Capabilities available when programming default CellGroup in NSA\n");
|
||||
|
||||
// This assert will never happen in the current implementation because NUMBER_OF_UE_MAX = 4.
|
||||
// However, if in the future NUMBER_OF_UE_MAX is increased, it will be necessary to improve the allocation of SRS resources,
|
||||
// where the startPosition = 2 or 3 and sl160 = 17, 17, 27 ... 157 only give us 30 different allocations.
|
||||
AssertFatal(uid>=0 && uid<30, "gNB cannot allocate the SRS resources\n");
|
||||
|
||||
int dl_antenna_ports = dl_antenna_ports_struct.N1 * dl_antenna_ports_struct.N2 * dl_antenna_ports_struct.XP;
|
||||
|
||||
uint64_t bitmap=0;
|
||||
switch (servingcellconfigcommon->ssb_PositionsInBurst->present) {
|
||||
case 1 :
|
||||
@@ -91,10 +95,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
secondaryCellGroup->cellGroupId = scg_id;
|
||||
NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig));
|
||||
nr_rlc_bearer_init(RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity);
|
||||
if (get_softmodem_params()->do_ra || get_softmodem_params()->sa)
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional);
|
||||
else
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional);
|
||||
//nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
|
||||
nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig);
|
||||
|
||||
secondaryCellGroup->rlc_BearerToAddModList = calloc(1,sizeof(*secondaryCellGroup->rlc_BearerToAddModList));
|
||||
@@ -338,12 +340,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL;
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL;
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1;
|
||||
if (!get_softmodem_params()->use_256qam_table) {
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL;
|
||||
} else {
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table));
|
||||
*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256;
|
||||
}
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL;
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI));
|
||||
*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1;
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling;
|
||||
@@ -607,43 +604,10 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1;
|
||||
if (!get_softmodem_params()->use_256qam_table) {
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL;
|
||||
} else {
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table));
|
||||
*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256;
|
||||
}
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI));
|
||||
*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling));
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize =
|
||||
calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize));
|
||||
*bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = NR_PDSCH_Config__prb_BundlingType__staticBundling__bundleSize_wideband;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->zp_CSI_RS_ResourceToAddModList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->zp_CSI_RS_ResourceToReleaseList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->aperiodic_ZP_CSI_RS_ResourceSetsToReleaseList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->sp_ZP_CSI_RS_ResourceSetsToAddModList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->sp_ZP_CSI_RS_ResourceSetsToReleaseList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->p_ZP_CSI_RS_ResourceSet=NULL;
|
||||
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToReleaseList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->vrb_ToPRB_Interleaver=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation=NR_PDSCH_Config__resourceAllocation_resourceAllocationType1;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_AggregationFactor=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternToAddModList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternToReleaseList=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1;
|
||||
if (!get_softmodem_params()->use_256qam_table) {
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL;
|
||||
} else {
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table));
|
||||
*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256;
|
||||
}
|
||||
set_dl_mcs_table(bwp->bwp_Common->genericParameters.subcarrierSpacing,
|
||||
configuration->force_256qam_off ? NULL : uecap,
|
||||
bwp->bwp_Dedicated,
|
||||
servingcellconfigcommon);
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI));
|
||||
*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1;
|
||||
bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling;
|
||||
@@ -746,8 +710,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
pusch_Config->pusch_TimeDomainAllocationList = NULL;
|
||||
pusch_Config->pusch_AggregationFactor=NULL;
|
||||
pusch_Config->mcs_Table=NULL;
|
||||
pusch_Config->mcs_TableTransformPrecoder=NULL;
|
||||
pusch_Config->transformPrecoder= NULL;
|
||||
pusch_Config->mcs_TableTransformPrecoder=NULL;
|
||||
/* if msg3_transformprecoding is set in conf file - pusch config should not disable it */
|
||||
if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) {
|
||||
pusch_Config->transformPrecoder=calloc(1,sizeof(*pusch_Config->transformPrecoder));
|
||||
@@ -808,7 +772,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id);
|
||||
srs_Config->srs_ResourceToReleaseList=NULL;
|
||||
|
||||
if(do_srs) {
|
||||
if (configuration->do_SRS) {
|
||||
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic;
|
||||
srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
|
||||
srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
|
||||
@@ -852,7 +816,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
srs_res0->freqHopping.b_SRS);
|
||||
srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither;
|
||||
|
||||
if(do_srs) {
|
||||
if (configuration->do_SRS) {
|
||||
srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_periodic;
|
||||
srs_res0->resourceType.choice.periodic=calloc(1,sizeof(*srs_res0->resourceType.choice.periodic));
|
||||
srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
|
||||
@@ -973,7 +937,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
long *delay[8];
|
||||
for (int i=0;i<8;i++) {
|
||||
delay[i] = calloc(1,sizeof(*delay[i]));
|
||||
*delay[i] = i+minRXTXTIME;
|
||||
*delay[i] = i + configuration->minRXTXTIME;
|
||||
ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]);
|
||||
}
|
||||
pucch_Config->spatialRelationInfoToAddModList = calloc(1,sizeof(*pucch_Config->spatialRelationInfoToAddModList));
|
||||
@@ -1368,17 +1332,17 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t));
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.size = 2;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 4;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=0;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]=16;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf[0] = 0;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf[1] = 16;
|
||||
resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1;
|
||||
resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM;
|
||||
break;
|
||||
case 2:
|
||||
resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t));
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.size = 1;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 2;
|
||||
resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=4;
|
||||
resourceMapping.frequencyDomainAllocation.choice.other.buf = calloc(2, sizeof(uint8_t));
|
||||
resourceMapping.frequencyDomainAllocation.choice.other.size = 1;
|
||||
resourceMapping.frequencyDomainAllocation.choice.other.bits_unused = 2;
|
||||
resourceMapping.frequencyDomainAllocation.choice.other.buf[0] = 4;
|
||||
resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p2;
|
||||
resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_fd_CDM2;
|
||||
break;
|
||||
@@ -1411,10 +1375,8 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
rrc_pdsch_AntennaPorts_t dl_antenna_ports,
|
||||
int minRXTXTIME,
|
||||
int do_csirs,
|
||||
int do_srs,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
const gNB_RrcConfigurationReq *configuration,
|
||||
int uid) {
|
||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||
AssertFatal(reconfig!=NULL,"reconfig is null\n");
|
||||
@@ -1425,12 +1387,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
fill_default_secondaryCellGroup(servingcellconfigcommon,
|
||||
servingcellconfigdedicated,
|
||||
secondaryCellGroup,
|
||||
uecap,
|
||||
1,
|
||||
1,
|
||||
dl_antenna_ports,
|
||||
minRXTXTIME,
|
||||
do_csirs,
|
||||
do_srs,
|
||||
configuration,
|
||||
uid);
|
||||
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#include <executables/softmodem-common.h>
|
||||
|
||||
#include "nr_nas_msg_sim.h"
|
||||
#include <openair2/RRC/NR/nr_rrc_proto.h>
|
||||
|
||||
NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
/* NAS Attach request with IMSI */
|
||||
@@ -178,27 +179,6 @@ static int nr_rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_NR_t subS
|
||||
return (0);
|
||||
}
|
||||
|
||||
extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
NR_SRB_ToAddModList_t *const srb2add_list,
|
||||
NR_DRB_ToAddModList_t *const drb2add_list,
|
||||
NR_DRB_ToReleaseList_t *const drb2release_list,
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
,rb_id_t *const defaultDRB,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const NR_SRB_ToAddModList_t * const srb2add_listP,
|
||||
const NR_DRB_ToAddModList_t * const drb2add_listP,
|
||||
const NR_DRB_ToReleaseList_t * const drb2release_listP,
|
||||
const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
|
||||
|
||||
// from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (encoded)
|
||||
int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const module_id_t module_id,
|
||||
const uint8_t *buffer,
|
||||
@@ -2230,7 +2210,7 @@ nr_rrc_ue_establish_srb2(
|
||||
// nr_rrc_ue_process_measConfig(ctxt_pP, gNB_index, ie->measConfig);
|
||||
}
|
||||
|
||||
if(ie->nonCriticalExtension->masterCellGroup!=NULL) {
|
||||
if((ie->nonCriticalExtension) && (ie->nonCriticalExtension->masterCellGroup!=NULL)) {
|
||||
nr_rrc_ue_process_masterCellGroup(
|
||||
ctxt_pP,
|
||||
gNB_index,
|
||||
@@ -2243,7 +2223,7 @@ nr_rrc_ue_establish_srb2(
|
||||
}
|
||||
|
||||
/* Check if there is dedicated NAS information to forward to NAS */
|
||||
if (ie->nonCriticalExtension->dedicatedNAS_MessageList != NULL) {
|
||||
if ((ie->nonCriticalExtension) && (ie->nonCriticalExtension->dedicatedNAS_MessageList != NULL)) {
|
||||
int list_count;
|
||||
uint32_t pdu_length;
|
||||
uint8_t *pdu_buffer;
|
||||
|
||||
@@ -1,607 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file pad_list.c
|
||||
* \brief list management primimtives
|
||||
* \author Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER, Navid Nikaein
|
||||
* \date 2012 - 2014
|
||||
* \version 0.5
|
||||
* @ingroup util
|
||||
*/
|
||||
//#define LIST_C
|
||||
//#define NULL 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "pad_list.h"
|
||||
//#include <mpi.h>
|
||||
|
||||
|
||||
void job_list_init (Job_List_t *listP) {
|
||||
listP->tail = NULL;
|
||||
listP->head = NULL;
|
||||
listP->nb_elements = 0;
|
||||
}
|
||||
|
||||
void event_list_init (Event_List_t *listP) {
|
||||
listP->tail = NULL;
|
||||
listP->head = NULL;
|
||||
listP->nb_elements = 0;
|
||||
}
|
||||
|
||||
void pkt_list_init (Packet_OTG_List_t *listP) {
|
||||
listP->tail = NULL;
|
||||
listP->head = NULL;
|
||||
listP->nb_elements = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void job_list_free (Job_List_t *listP) {
|
||||
Job_elt_t *le;
|
||||
|
||||
while ((le = job_list_remove_head (listP))) {
|
||||
free(le);
|
||||
}
|
||||
}
|
||||
|
||||
void event_list_free (Event_List_t *listP) {
|
||||
Event_elt_t *le;
|
||||
|
||||
while ((le = event_list_remove_head (listP))) {
|
||||
free(le);
|
||||
}
|
||||
}
|
||||
|
||||
void pkt_list_free (Packet_OTG_List_t *listP) {
|
||||
Packet_otg_elt_t *le;
|
||||
|
||||
while ((le = pkt_list_remove_head (listP))) {
|
||||
free(le);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Job_elt_t *job_list_get_head (Job_List_t *listP) {
|
||||
return listP->head;
|
||||
}
|
||||
|
||||
Event_elt_t *event_list_get_head (Event_List_t *listP) {
|
||||
return listP->head;
|
||||
}
|
||||
|
||||
Packet_otg_elt_t *pkt_list_get_head (Packet_OTG_List_t *listP) {
|
||||
return listP->head;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* remove an element from head of a list
|
||||
* @param pointer on targeted list
|
||||
* @return pointer on removed Job_elt_t
|
||||
*/
|
||||
Job_elt_t *job_list_remove_head (Job_List_t *listP) {
|
||||
// access optimisation
|
||||
Job_elt_t *head;
|
||||
head = listP->head;
|
||||
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
} else {
|
||||
//msg("[MEM_MGT][WARNING] remove_head_from_list(%s) no elements\n",listP->name);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
Event_elt_t *event_list_remove_head (Event_List_t *listP) {
|
||||
// access optimisation
|
||||
Event_elt_t *head;
|
||||
head = listP->head;
|
||||
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
} else {
|
||||
//msg("[MEM_MGT][WARNING] remove_head_from_list(%s) no elements\n",listP->name);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
Packet_otg_elt_t *pkt_list_remove_head (Packet_OTG_List_t *listP) {
|
||||
// access optimisation
|
||||
Packet_otg_elt_t *head;
|
||||
head = listP->head;
|
||||
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
} else {
|
||||
//msg("[MEM_MGT][WARNING] remove_head_from_list(%s) no elements\n",listP->name);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Job_elt_t *job_list_remove_element (Job_elt_t *elementP, Job_List_t *listP) {
|
||||
// access optimisation;
|
||||
Job_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// test head
|
||||
head = listP->head;
|
||||
|
||||
if (listP->head == elementP) {
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (head) {
|
||||
if (head->next == elementP) {
|
||||
head->next = elementP->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
if (listP->tail == elementP) {
|
||||
listP->tail = head;
|
||||
}
|
||||
|
||||
return elementP;
|
||||
} else {
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elementP;
|
||||
}
|
||||
|
||||
Event_elt_t *event_list_remove_element (Event_elt_t *elementP, Event_List_t *listP) {
|
||||
// access optimisation;
|
||||
Event_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// test head
|
||||
head = listP->head;
|
||||
|
||||
if (listP->head == elementP) {
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (head) {
|
||||
if (head->next == elementP) {
|
||||
head->next = elementP->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
if (listP->tail == elementP) {
|
||||
listP->tail = head;
|
||||
}
|
||||
|
||||
return elementP;
|
||||
} else {
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elementP;
|
||||
}
|
||||
|
||||
Packet_otg_elt_t *pkt_list_remove_element (Packet_otg_elt_t *elementP, Packet_OTG_List_t *listP) {
|
||||
// access optimisation;
|
||||
Packet_otg_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// test head
|
||||
head = listP->head;
|
||||
|
||||
if (listP->head == elementP) {
|
||||
// almost one element
|
||||
if (head != NULL) {
|
||||
listP->head = head->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
// if only one element, update tail
|
||||
if (listP->head == NULL) {
|
||||
listP->tail = NULL;
|
||||
} else {
|
||||
head->next = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (head) {
|
||||
if (head->next == elementP) {
|
||||
head->next = elementP->next;
|
||||
listP->nb_elements = listP->nb_elements - 1;
|
||||
|
||||
if (listP->tail == elementP) {
|
||||
listP->tail = head;
|
||||
}
|
||||
|
||||
return elementP;
|
||||
} else {
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elementP;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
* add an element to the beginning of a list
|
||||
* @param pointer on targeted list
|
||||
* @return pointer on removed Job_elt_t
|
||||
*/
|
||||
|
||||
void job_list_add_head (Job_elt_t *elementP, Job_List_t *listP) {
|
||||
// access optimisation;
|
||||
Job_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
head = listP->head;
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
|
||||
// almost one element
|
||||
if (head == NULL) {
|
||||
listP->head = elementP;
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
elementP->next = head;
|
||||
listP->head = elementP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void event_list_add_head (Event_elt_t *elementP, Event_List_t *listP) {
|
||||
// access optimisation;
|
||||
Event_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
head = listP->head;
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
|
||||
// almost one element
|
||||
if (head == NULL) {
|
||||
listP->head = elementP;
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
elementP->next = head;
|
||||
listP->head = elementP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pkt_list_add_head (Packet_otg_elt_t *elementP, Packet_OTG_List_t *listP) {
|
||||
// access optimisation;
|
||||
Packet_otg_elt_t *head;
|
||||
|
||||
if (elementP != NULL) {
|
||||
head = listP->head;
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
|
||||
// almost one element
|
||||
if (head == NULL) {
|
||||
listP->head = elementP;
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
elementP->next = head;
|
||||
listP->head = elementP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void event_list_add_element (Event_elt_t *elementP, Event_elt_t *previous, Event_List_t *listP) {
|
||||
// access optimisation;
|
||||
Event_elt_t *next;
|
||||
|
||||
if (elementP != NULL && previous != NULL) {
|
||||
elementP->next = NULL;
|
||||
next = previous->next;
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
|
||||
// almost one element
|
||||
if (next == NULL) {
|
||||
previous->next = elementP;
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
elementP->next = previous->next;
|
||||
previous->next = elementP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
* add an element to the end of a list
|
||||
* @param pointer on targeted list
|
||||
* @return pointer on removed Job_elt_t
|
||||
*/
|
||||
void job_list_add_tail_eurecom (Job_elt_t *elementP, Job_List_t *listP) {
|
||||
Job_elt_t *tail;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// access optimisation
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
elementP->next = NULL;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = elementP;
|
||||
} else {
|
||||
tail->next = elementP;
|
||||
}
|
||||
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
//msg("[CNT_LIST][ERROR] add_cnt_tail() element NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
void event_list_add_tail_eurecom (Event_elt_t *elementP, Event_List_t *listP) {
|
||||
Event_elt_t *tail;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// access optimisation
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
elementP->next = NULL;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = elementP;
|
||||
} else {
|
||||
tail->next = elementP;
|
||||
}
|
||||
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
//msg("[CNT_LIST][ERROR] add_cnt_tail() element NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
void pkt_list_add_tail_eurecom (Packet_otg_elt_t *elementP, Packet_OTG_List_t *listP) {
|
||||
Packet_otg_elt_t *tail;
|
||||
|
||||
if (elementP != NULL) {
|
||||
// access optimisation
|
||||
listP->nb_elements = listP->nb_elements + 1;
|
||||
elementP->next = NULL;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = elementP;
|
||||
} else {
|
||||
tail->next = elementP;
|
||||
}
|
||||
|
||||
listP->tail = elementP;
|
||||
} else {
|
||||
//msg("[CNT_LIST][ERROR] add_cnt_tail() element NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void job_list_add_list (Job_List_t *sublistP, Job_List_t *listP) {
|
||||
if (sublistP) {
|
||||
if (sublistP->head) {
|
||||
// access optimisation
|
||||
Job_elt_t *tail;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = sublistP->head;
|
||||
} else {
|
||||
tail->next = sublistP->head;
|
||||
}
|
||||
|
||||
listP->tail = sublistP->tail;
|
||||
// clear sublist
|
||||
sublistP->head = NULL;
|
||||
sublistP->tail = NULL;
|
||||
listP->nb_elements = listP->nb_elements + sublistP->nb_elements;
|
||||
sublistP->nb_elements = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void event_list_add_list (Event_List_t *sublistP, Event_List_t *listP) {
|
||||
if (sublistP) {
|
||||
if (sublistP->head) {
|
||||
// access optimisation
|
||||
Event_elt_t *tail;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = sublistP->head;
|
||||
} else {
|
||||
tail->next = sublistP->head;
|
||||
}
|
||||
|
||||
listP->tail = sublistP->tail;
|
||||
// clear sublist
|
||||
sublistP->head = NULL;
|
||||
sublistP->tail = NULL;
|
||||
listP->nb_elements = listP->nb_elements + sublistP->nb_elements;
|
||||
sublistP->nb_elements = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pkt_list_add_list (Packet_OTG_List_t *sublistP, Packet_OTG_List_t *listP) {
|
||||
if (sublistP) {
|
||||
if (sublistP->head) {
|
||||
// access optimisation
|
||||
Packet_otg_elt_t *tail;
|
||||
tail = listP->tail;
|
||||
|
||||
// almost one element
|
||||
if (tail == NULL) {
|
||||
listP->head = sublistP->head;
|
||||
} else {
|
||||
tail->next = sublistP->head;
|
||||
}
|
||||
|
||||
listP->tail = sublistP->tail;
|
||||
// clear sublist
|
||||
sublistP->head = NULL;
|
||||
sublistP->tail = NULL;
|
||||
listP->nb_elements = listP->nb_elements + sublistP->nb_elements;
|
||||
sublistP->nb_elements = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void job_list_display (Job_List_t *listP) {
|
||||
//Correct the output once the content of struct Job is fixed
|
||||
/*Job_elt_t *cursor;
|
||||
unsigned short nb_elements = 0;
|
||||
|
||||
if (listP) {
|
||||
cursor = listP->head;
|
||||
if (cursor) {
|
||||
while (cursor != NULL) {
|
||||
if (cursor->job.type == eNB_DL)
|
||||
printf ("DL eNB From (%d,%d)\n", (cursor->job).nid, (cursor->job).mid);
|
||||
else if (cursor->job.type == UE_DL)
|
||||
printf ("DL UE From (%d,%d)\n", (cursor->job).nid, (cursor->job).mid);
|
||||
else if (cursor->job.type == UE_UL)
|
||||
printf ("UL UE From (%d,%d)\n", (cursor->job).nid, (cursor->job).mid);
|
||||
else if (cursor->job.type == eNB_UL)
|
||||
printf ("UL eNB From (%d,%d)\n", (cursor->job).nid, (cursor->job).mid);
|
||||
//msg ("From (%d,%d) To (%d,%d)\n", (cursor->job).node1, (cursor->job).master1, (cursor->job).node2, (cursor->job).master2);
|
||||
cursor = cursor->next;
|
||||
nb_elements++;
|
||||
}
|
||||
printf ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
//msg ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
}
|
||||
} else {
|
||||
printf ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
//msg ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
}*/
|
||||
}
|
||||
|
||||
void event_list_display (Event_List_t *listP) {
|
||||
Event_elt_t *cursor;
|
||||
unsigned short nb_elements = 0;
|
||||
|
||||
if (listP) {
|
||||
cursor = listP->head;
|
||||
|
||||
if (cursor) {
|
||||
while (cursor != NULL) {
|
||||
printf ("Ev (%d,%d)\n", (cursor->event).type, (cursor->event).frame);
|
||||
//msg ("From (%d,%d) To (%d,%d)\n", (cursor->job).node1, (cursor->job).master1, (cursor->job).node2, (cursor->job).master2);
|
||||
cursor = cursor->next;
|
||||
nb_elements++;
|
||||
}
|
||||
|
||||
printf ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
//msg ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
}
|
||||
} else {
|
||||
printf ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
//msg ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
void pkt_list_display (Packet_OTG_List_t *listP) {
|
||||
Packet_otg_elt_t *cursor;
|
||||
unsigned short nb_elements = 0;
|
||||
|
||||
if (listP) {
|
||||
cursor = listP->head;
|
||||
|
||||
if (cursor) {
|
||||
while (cursor != NULL) {
|
||||
printf ("Pkt (DST %d, RB %ld)\n", (cursor->otg_pkt).dst_id, (cursor->otg_pkt).rb_id);
|
||||
//msg ("From (%d,%d) To (%d,%d)\n", (cursor->job).node1, (cursor->job).master1, (cursor->job).node2, (cursor->job).master2);
|
||||
cursor = cursor->next;
|
||||
nb_elements++;
|
||||
}
|
||||
|
||||
printf ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
//msg ("Found nb_elements %d nb_elements %d\n", nb_elements, listP->nb_elements);
|
||||
}
|
||||
} else {
|
||||
printf ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
//msg ("[SDU_MNGT][WARNING] display_cnt_dbl_lk_list_up() : list is NULL\n");
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file pad_list.c
|
||||
* \brief list management primimtives
|
||||
* \author Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER, Navid Nikaein
|
||||
* \date 2012 - 2014
|
||||
* \version 0.5
|
||||
* @ingroup util
|
||||
*/
|
||||
|
||||
#ifndef __list_H__
|
||||
#define __list_H__
|
||||
|
||||
#include "types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct Job_List_s {
|
||||
Job_elt_t *head;
|
||||
Job_elt_t *tail;
|
||||
int nb_elements;
|
||||
} Job_List_t;
|
||||
|
||||
typedef struct Event_List_s {
|
||||
Event_elt_t *head;
|
||||
Event_elt_t *tail;
|
||||
int nb_elements;
|
||||
} Event_List_t;
|
||||
|
||||
typedef struct Packet_OTG_List_s {
|
||||
Packet_otg_elt_t *head;
|
||||
Packet_otg_elt_t *tail;
|
||||
int nb_elements;
|
||||
} Packet_OTG_List_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void job_list_init (Job_List_t*);
|
||||
void job_list_free (Job_List_t* listP);
|
||||
Job_elt_t* job_list_get_head (Job_List_t*);
|
||||
Job_elt_t* job_list_remove_head (Job_List_t* );
|
||||
Job_elt_t* job_list_remove_element (Job_elt_t*, Job_List_t*);
|
||||
void job_list_add_head (Job_elt_t* , Job_List_t* );
|
||||
void job_list_add_tail_eurecom (Job_elt_t* , Job_List_t* );
|
||||
void job_list_add_list (Job_List_t* , Job_List_t* );
|
||||
void job_list_display (Job_List_t* );
|
||||
|
||||
void event_list_init (Event_List_t*);
|
||||
void event_list_free (Event_List_t* listP);
|
||||
Event_elt_t* event_list_get_head (Event_List_t*);
|
||||
Event_elt_t* event_list_remove_head (Event_List_t* );
|
||||
Event_elt_t* event_list_remove_element (Event_elt_t*, Event_List_t*);
|
||||
void event_list_add_head (Event_elt_t* , Event_List_t* );
|
||||
void event_list_add_element (Event_elt_t* , Event_elt_t* , Event_List_t* );
|
||||
void event_list_add_tail_eurecom (Event_elt_t* , Event_List_t* );
|
||||
void event_list_add_list (Event_List_t* , Event_List_t* );
|
||||
void event_list_display (Event_List_t* );
|
||||
|
||||
void pkt_list_init (Packet_OTG_List_t*);
|
||||
void pkt_list_free (Packet_OTG_List_t* listP);
|
||||
Packet_otg_elt_t* pkt_list_get_head (Packet_OTG_List_t*);
|
||||
Packet_otg_elt_t* pkt_list_remove_head (Packet_OTG_List_t* );
|
||||
Packet_otg_elt_t* pkt_list_remove_element (Packet_otg_elt_t*, Packet_OTG_List_t*);
|
||||
void pkt_list_add_head (Packet_otg_elt_t* , Packet_OTG_List_t* );
|
||||
void pkt_list_add_element (Packet_otg_elt_t* , Packet_otg_elt_t* , Packet_OTG_List_t* );
|
||||
void pkt_list_add_tail_eurecom (Packet_otg_elt_t* , Packet_OTG_List_t* );
|
||||
void pkt_list_add_list (Packet_OTG_List_t* , Packet_OTG_List_t* );
|
||||
void pkt_list_display (Packet_OTG_List_t* );
|
||||
|
||||
#endif
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file pad_list.c
|
||||
* \brief list management primimtives
|
||||
* \author Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER, Navid Nikaein
|
||||
* \date 2012 - 2014
|
||||
* \version 0.5
|
||||
* @ingroup util
|
||||
*/
|
||||
|
||||
#ifndef __FIFO_TYPES_H__
|
||||
#define __FIFO_TYPES_H__
|
||||
#include "platform_types.h"
|
||||
|
||||
/* Types regrouping both user-defined and regular events */
|
||||
typedef enum {
|
||||
MIN_ET=0,
|
||||
OAI_ET=MIN_ET, // config events
|
||||
SYS_ET,
|
||||
TOPO_ET,
|
||||
APP_ET,
|
||||
EMU_ET,
|
||||
DL_ET, // frame events
|
||||
UL_ET,
|
||||
S_ET,
|
||||
PHY_ET, // protocol events
|
||||
MAC_ET,
|
||||
RLC_ET,
|
||||
PDCP_ET,
|
||||
RRC_ET,
|
||||
MAX_ET
|
||||
} Event_Type_t;
|
||||
|
||||
/* decomposition of node functions into jobs for a given event */
|
||||
typedef enum Job_type_e { JT_OTG, JT_PDCP, JT_PHY_MAC, JT_INIT_SYNC, JT_DL, JT_UL, RN_DL, RN_UL, JT_END} Job_Type_t;
|
||||
|
||||
typedef enum Operation_Type_e { READ, WRITE, RESET} Operation_Type_t;
|
||||
|
||||
typedef struct Job_s {
|
||||
enum Job_type_e type;
|
||||
int exe_time; /* execution time at the worker*/
|
||||
int nid; /* node id*/
|
||||
eNB_flag_t eNB_flag;
|
||||
frame_t frame;
|
||||
int last_slot;
|
||||
int next_slot;
|
||||
int ctime;
|
||||
} Job_t;
|
||||
|
||||
typedef struct Signal_buffers_s { // (s = transmit, r,r0 = receive)
|
||||
double **s_re;
|
||||
double **s_im;
|
||||
double **r_re;
|
||||
double **r_im;
|
||||
double **r_re0;
|
||||
double **r_im0;
|
||||
} Signal_buffers_t;
|
||||
|
||||
/*!\brief sybframe type : DL, UL, SF, */
|
||||
|
||||
typedef struct Packet_otg_s {
|
||||
unsigned int sdu_buffer_size;
|
||||
unsigned char *sdu_buffer;
|
||||
module_id_t module_id;
|
||||
rb_id_t rb_id;
|
||||
module_id_t dst_id;
|
||||
boolean_t is_ue;
|
||||
pdcp_transmission_mode_t mode;
|
||||
} Packet_otg_t;
|
||||
|
||||
typedef struct {
|
||||
Event_Type_t type;
|
||||
enum Operation_Type_e optype; //op
|
||||
char *key;
|
||||
void *value;
|
||||
frame_t frame;
|
||||
int ue;
|
||||
int lcid;
|
||||
} Event_t;
|
||||
|
||||
/*typedef struct Global_Time {
|
||||
uint32_t frame;
|
||||
int32_t slot;
|
||||
int32_t last_slot;
|
||||
int32_t next_slot;
|
||||
double time_s;
|
||||
double time_ms;
|
||||
};*/
|
||||
|
||||
|
||||
|
||||
typedef struct Packet_otg_elt_s {
|
||||
struct Packet_otg_elt_s *next;
|
||||
struct Packet_otg_elt_s *previous;
|
||||
Packet_otg_t otg_pkt;
|
||||
} Packet_otg_elt_t;
|
||||
|
||||
typedef struct Job_element_s {
|
||||
struct Job_element_s *next;
|
||||
Job_t job;
|
||||
} Job_elt_t;
|
||||
|
||||
typedef struct Event_element_s {
|
||||
struct Event_element_s *next;
|
||||
struct Event_element_s *previous;
|
||||
Event_t event;
|
||||
} Event_elt_t;
|
||||
#endif
|
||||
@@ -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"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user