Merge branch 'episys/master' into episys-merge
Conflicts: common/utils/LOG/log.h common/utils/ocp_itti/intertask_interface.cpp nfapi/oai_integration/nfapi_vnf.c nfapi/open-nFAPI/nfapi/src/nfapi.c openair2/LAYER2/MAC/main_ue.c openair2/LAYER2/PDCP_v10.1.0/pdcp.c openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c openair2/PHY_INTERFACE/phy_stub_UE.c openair2/RRC/LTE/rrc_UE.c openair2/RRC/LTE/rrc_eNB.c openair3/NAS/UE/ESM/esm_ebr_context.c targets/COMMON/openairinterface5g_limits.h targets/RT/USER/lte-softmodem.c targets/RT/USER/lte-uesoftmodem.c
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/queue_test
|
||||
@@ -22,25 +22,31 @@ extern UL_RCC_IND_t UL_RCC_INFO;
|
||||
uint16_t frame_cnt=0;
|
||||
void handle_rach(UL_IND_t *UL_info) {
|
||||
int i;
|
||||
|
||||
if(NFAPI_MODE == NFAPI_MODE_VNF) {
|
||||
for(uint8_t j = 0; j < NUM_NFPAI_SUBFRAME; j++) {
|
||||
if (UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles>0) {
|
||||
AssertFatal(UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
|
||||
LOG_D(MAC,"UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:SFN/SF:%d\n",UL_info->frame,UL_info->subframe, NFAPI_SFNSF2DEC(UL_RCC_INFO.rach_ind[j].sfn_sf));
|
||||
initiate_ra_proc(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
NFAPI_SFNSF2SFN(UL_RCC_INFO.rach_ind[j].sfn_sf),
|
||||
NFAPI_SFNSF2SF(UL_RCC_INFO.rach_ind[j].sfn_sf),
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.preamble,
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.rnti,
|
||||
0
|
||||
);
|
||||
free(UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list);
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles = 0;
|
||||
UL_RCC_INFO.rach_ind[j].header.message_id = 0;
|
||||
int j = UL_info->subframe;
|
||||
AssertFatal(j < sizeof(UL_RCC_INFO.rach_ind) / sizeof(UL_RCC_INFO.rach_ind[0]), "j index out of range of index of rach_ind\n");
|
||||
if (NFAPI_MODE == NFAPI_MODE_VNF)
|
||||
{
|
||||
if (UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles > 0)
|
||||
{
|
||||
if (UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles > 1)
|
||||
{
|
||||
LOG_D(MAC, "handle_rach j: %d UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles: %d\n",
|
||||
j, UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles);
|
||||
LOG_D(MAC, "UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:Frame: %d Subframe: %d\n",
|
||||
UL_info->frame, UL_info->subframe, NFAPI_SFNSF2SFN(UL_RCC_INFO.rach_ind[j].sfn_sf), NFAPI_SFNSF2SF(UL_RCC_INFO.rach_ind[j].sfn_sf));
|
||||
}
|
||||
AssertFatal(UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles == 1, "More than 1 preamble not supported\n"); // dump frame/sf and all things in UL_RCC_INFO
|
||||
initiate_ra_proc(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
NFAPI_SFNSF2SFN(UL_RCC_INFO.rach_ind[j].sfn_sf),
|
||||
NFAPI_SFNSF2SF(UL_RCC_INFO.rach_ind[j].sfn_sf),
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.preamble,
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.rnti,
|
||||
0);
|
||||
free(UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list);
|
||||
UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles = 0;
|
||||
UL_RCC_INFO.rach_ind[j].header.message_id = 0;
|
||||
}
|
||||
} else {
|
||||
if (UL_info->rach_ind.rach_indication_body.number_of_preambles>0) {
|
||||
@@ -788,6 +794,7 @@ IF_Module_t *IF_Module_init(int Mod_id) {
|
||||
"allocation of if_inst[%d]->if_mutex fails\n",Mod_id);
|
||||
}
|
||||
|
||||
memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_INFO));
|
||||
return if_inst[Mod_id];
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ typedef struct {
|
||||
} UL_IND_t;
|
||||
|
||||
// Downlink subframe P7
|
||||
#define NUM_NFPAI_SUBFRAME 5
|
||||
#define NUM_NFPAI_SUBFRAME 10
|
||||
typedef struct {
|
||||
/// harq indication list
|
||||
nfapi_harq_indication_t harq_ind[NUM_NFPAI_SUBFRAME];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,21 +13,19 @@
|
||||
#include "openair2/PHY_INTERFACE/IF_Module.h"
|
||||
#include "nfapi_interface.h"
|
||||
#include "nfapi_pnf_interface.h"
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
|
||||
//#include "openair1/PHY/defs.h"
|
||||
//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
|
||||
#include "queue.h"
|
||||
|
||||
//below 2 difinitions move to phy_stub_UE.c to add initialization when difinition.
|
||||
extern UL_IND_t *UL_INFO;
|
||||
extern nfapi_tx_request_pdu_t* tx_request_pdu_list;
|
||||
// New
|
||||
/// Pointers to config_request types. Used from nfapi callback functions.
|
||||
//below 3 difinitions move to phy_stub_UE.c to add initialization when difinition.
|
||||
extern nfapi_dl_config_request_t* dl_config_req;
|
||||
extern nfapi_ul_config_request_t* ul_config_req;
|
||||
extern nfapi_hi_dci0_request_t* hi_dci0_req;
|
||||
|
||||
int tx_req_num_elems;
|
||||
|
||||
//below 2 difinitions move to lte-ue.c to add initialization when difinition.
|
||||
//int next_ra_frame;
|
||||
@@ -61,16 +59,19 @@ void send_nfapi_UL_indications(UL_IND_t UL_INFO);
|
||||
|
||||
//void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe);
|
||||
|
||||
void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen, uint16_t rnti, int index);
|
||||
void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen, uint16_t rnti, int index,
|
||||
nfapi_ul_config_request_t *ul_config_req);
|
||||
|
||||
|
||||
// This function should be indicating directly to the eNB when there is a planned scheduling request at the MAC layer
|
||||
// of the UE. It should get called from ue_get_SR()
|
||||
void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti);
|
||||
void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti,
|
||||
nfapi_ul_config_request_t *ul_config_req);
|
||||
|
||||
// In our case the this function will be always indicating ACK to the MAC of the eNB (i.e. always assuming)
|
||||
// successful decoding.
|
||||
void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti);
|
||||
void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti,
|
||||
nfapi_ul_config_request_t *ul_config_req);
|
||||
|
||||
|
||||
void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI);
|
||||
@@ -79,9 +80,11 @@ void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL
|
||||
void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti);
|
||||
|
||||
|
||||
void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti);
|
||||
void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti,
|
||||
nfapi_ul_config_request_t *ul_config_req);
|
||||
|
||||
void fill_uci_harq_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO,nfapi_ul_config_harq_information *harq_information, uint16_t rnti
|
||||
void fill_uci_harq_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO,nfapi_ul_config_harq_information *harq_information, uint16_t rnti,
|
||||
nfapi_ul_config_request_t *ul_config_req
|
||||
/*uint8_t tdd_mapping_mode,
|
||||
uint16_t tdd_multiplexing_mask*/);
|
||||
|
||||
@@ -89,13 +92,29 @@ int ul_config_req_UE_MAC(nfapi_ul_config_request_t* req, int frame, int subframe
|
||||
|
||||
void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id,
|
||||
nfapi_ul_config_request_pdu_t *ul_config_pdu,
|
||||
uint16_t frame,uint8_t subframe,uint8_t srs_present, int index);
|
||||
uint16_t frame,uint8_t subframe,uint8_t srs_present, int index,
|
||||
nfapi_ul_config_request_t *ul_config_req);
|
||||
|
||||
typedef struct nfapi_tx_req_pdu_list_t
|
||||
{
|
||||
int num_pdus; /* number .pdus[] objects */
|
||||
nfapi_tx_request_pdu_t pdus[]; /* see "struct hack" */
|
||||
} nfapi_tx_req_pdu_list_t;
|
||||
|
||||
typedef struct nfapi_dl_config_req_tx_req_t
|
||||
{
|
||||
nfapi_dl_config_request_t *dl_config_req;
|
||||
nfapi_tx_req_pdu_list_t *tx_req_pdu_list;
|
||||
} nfapi_dl_config_req_tx_req_t;
|
||||
|
||||
void nfapi_free_tx_req_pdu_list(nfapi_tx_req_pdu_list_t *);
|
||||
|
||||
void dl_config_req_UE_MAC_dci(int sfn,
|
||||
int sf,
|
||||
nfapi_dl_config_request_pdu_t *dci,
|
||||
nfapi_dl_config_request_pdu_t *dlsch,
|
||||
int num_ue);
|
||||
int num_ue,
|
||||
nfapi_tx_req_pdu_list_t *);
|
||||
void dl_config_req_UE_MAC_bch(int sfn,
|
||||
int sf,
|
||||
nfapi_dl_config_request_pdu_t *bch,
|
||||
@@ -103,7 +122,8 @@ void dl_config_req_UE_MAC_bch(int sfn,
|
||||
void dl_config_req_UE_MAC_mch(int sfn,
|
||||
int sf,
|
||||
nfapi_dl_config_request_pdu_t *bch,
|
||||
int num_ue);
|
||||
int num_ue,
|
||||
nfapi_tx_req_pdu_list_t *);
|
||||
|
||||
int tx_req_UE_MAC(nfapi_tx_request_t* req);
|
||||
|
||||
@@ -129,6 +149,38 @@ int memcpy_hi_dci0_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfa
|
||||
|
||||
void UE_config_stub_pnf(void);
|
||||
|
||||
void *memcpy_tx_req_standalone(nfapi_tx_request_t *tx_req);
|
||||
|
||||
void *memcpy_dl_config_req_standalone(nfapi_dl_config_request_t *dl_config_req);
|
||||
|
||||
// open an SCTP socket with a standalone PNF module
|
||||
void ue_init_standalone_socket(const char *addr, int tx_port, int rx_port);
|
||||
|
||||
// read from standalone pnf socket call corresponding memcpy functions
|
||||
void *ue_standalone_pnf_task(void *context);
|
||||
void send_standalone_msg(UL_IND_t *UL, nfapi_message_id_e msg_type);
|
||||
void send_standalone_dummy(void);
|
||||
void enqueue_dl_config_req_tx_req(nfapi_dl_config_request_t *dl_config_req, nfapi_tx_request_t *tx_req);
|
||||
|
||||
// Convert downlink nfapi messages to a string.
|
||||
// Returned memory is malloc'ed, caller is responsible for freeing.
|
||||
char *nfapi_dl_config_req_to_string(nfapi_dl_config_request_t *req);
|
||||
char *nfapi_ul_config_req_to_string(nfapi_ul_config_request_t *req);
|
||||
|
||||
// Convert downlink nfapi messages to a string.
|
||||
// Returned memory is statically allocated.
|
||||
const char *dl_pdu_type_to_string(uint8_t pdu_type);
|
||||
const char *ul_pdu_type_to_string(uint8_t pdu_type);
|
||||
|
||||
extern queue_t dl_config_req_tx_req_queue;
|
||||
extern queue_t ul_config_req_queue;
|
||||
extern queue_t hi_dci0_req_queue;
|
||||
|
||||
extern nfapi_ul_config_request_t* ul_config_req;
|
||||
extern nfapi_hi_dci0_request_t* hi_dci0_req;
|
||||
|
||||
extern int current_sfn_sf;
|
||||
|
||||
extern sem_t sfn_semaphore;
|
||||
|
||||
#endif /* PHY_STUB_UE_H_ */
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
#include "queue.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <stdio.h>
|
||||
#define LOG_ERROR(MSG) printf(MSG "\n")
|
||||
#else
|
||||
#include "common/utils/LOG/log.h"
|
||||
#define LOG_ERROR(MSG) LOG_E(PHY, MSG "\n")
|
||||
#endif
|
||||
|
||||
void init_queue(queue_t *q)
|
||||
{
|
||||
memset(q, 0, sizeof(*q));
|
||||
pthread_mutex_init(&q->mutex, NULL);
|
||||
}
|
||||
|
||||
bool put_queue(queue_t *q, void *item)
|
||||
{
|
||||
assert(item != NULL);
|
||||
if (pthread_mutex_lock(&q->mutex) != 0)
|
||||
{
|
||||
LOG_ERROR("put_queue: mutex_lock failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool queued;
|
||||
if (q->num_items >= MAX_QUEUE_SIZE)
|
||||
{
|
||||
LOG_ERROR("put_queue: queue is full");
|
||||
queued = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(q->items[q->write_index] == NULL);
|
||||
q->items[q->write_index] = item;
|
||||
q->write_index = (q->write_index + 1) % MAX_QUEUE_SIZE;
|
||||
q->num_items++;
|
||||
queued = true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return queued;
|
||||
}
|
||||
|
||||
void *get_queue(queue_t *q)
|
||||
{
|
||||
void *item = NULL;
|
||||
if (pthread_mutex_lock(&q->mutex) != 0)
|
||||
{
|
||||
LOG_ERROR("get_queue: mutex_lock failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (q->num_items > 0)
|
||||
{
|
||||
item = q->items[q->read_index];
|
||||
assert(item != NULL);
|
||||
q->items[q->read_index] = NULL;
|
||||
q->read_index = (q->read_index + 1) % MAX_QUEUE_SIZE;
|
||||
q->num_items--;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return item;
|
||||
}
|
||||
|
||||
bool requeue(queue_t *q, void *item)
|
||||
{
|
||||
assert(item != NULL);
|
||||
if (pthread_mutex_lock(&q->mutex) != 0)
|
||||
{
|
||||
LOG_ERROR("requeue: mutex_lock failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool queued;
|
||||
if (q->num_items >= MAX_QUEUE_SIZE)
|
||||
{
|
||||
LOG_ERROR("requeue: queue is full");
|
||||
queued = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->read_index = (q->read_index + MAX_QUEUE_SIZE - 1) % MAX_QUEUE_SIZE;
|
||||
assert(q->items[q->read_index] == NULL);
|
||||
q->items[q->read_index] = item;
|
||||
q->num_items++;
|
||||
queued = true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return queued;
|
||||
}
|
||||
|
||||
void *unqueue(queue_t *q)
|
||||
{
|
||||
void *item = NULL;
|
||||
if (pthread_mutex_lock(&q->mutex) != 0) {
|
||||
LOG_ERROR("unqueue: mutex_lock failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (q->num_items > 0) {
|
||||
q->write_index = (q->write_index + MAX_QUEUE_SIZE - 1) % MAX_QUEUE_SIZE;
|
||||
item = q->items[q->write_index];
|
||||
q->items[q->write_index] = NULL;
|
||||
q->num_items--;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return item;
|
||||
}
|
||||
|
||||
void *unqueue_matching(queue_t *q, size_t max_depth, queue_matcher_t *matcher, void *wanted)
|
||||
{
|
||||
if (pthread_mutex_lock(&q->mutex) != 0)
|
||||
{
|
||||
LOG_ERROR("unqueue_matching: mutex_lock failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *item = NULL;
|
||||
size_t endi = q->write_index;
|
||||
for (size_t i = 0; i < q->num_items; i++)
|
||||
{
|
||||
if (max_depth == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
--max_depth;
|
||||
|
||||
endi = (endi + MAX_QUEUE_SIZE - 1) % MAX_QUEUE_SIZE;
|
||||
void *candidate = q->items[endi];
|
||||
if (matcher(wanted, candidate))
|
||||
{
|
||||
item = candidate;
|
||||
// delete item from the queue and move other items down
|
||||
for (;;)
|
||||
{
|
||||
size_t j = (endi + 1) % MAX_QUEUE_SIZE;
|
||||
if (j == q->write_index)
|
||||
{
|
||||
q->items[endi] = NULL;
|
||||
q->write_index = endi;
|
||||
q->num_items--;
|
||||
break;
|
||||
}
|
||||
q->items[endi] = q->items[j];
|
||||
endi = j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
queue_t is a basic thread-safe non-blocking fixed-size queue.
|
||||
|
||||
put_queue returns false if the queue is full.
|
||||
get_queue returns NULL if the queue is empty.
|
||||
|
||||
Example usage:
|
||||
|
||||
// Initialization:
|
||||
queue_t fooq;
|
||||
init_queue(&fooq);
|
||||
|
||||
// Producer:
|
||||
foo_t *item = new_foo();
|
||||
if (!put_queue(&fooq, item))
|
||||
delete_foo(item);
|
||||
|
||||
// Consumer:
|
||||
foo_t *item = get_queue(&fooq);
|
||||
if (item)
|
||||
{
|
||||
do_something_with_foo(item);
|
||||
delete_foo(item);
|
||||
}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_QUEUE_SIZE 512
|
||||
|
||||
typedef struct queue_t
|
||||
{
|
||||
void *items[MAX_QUEUE_SIZE];
|
||||
size_t read_index, write_index;
|
||||
size_t num_items;
|
||||
pthread_mutex_t mutex;
|
||||
} queue_t;
|
||||
|
||||
void init_queue(queue_t *q);
|
||||
bool put_queue(queue_t *q, void *item);
|
||||
void *get_queue(queue_t *q);
|
||||
|
||||
/* Put the given item back onto this queue at the head.
|
||||
(The next call to put_queue would return this item.)
|
||||
Return true if successful, false if the queue was full */
|
||||
bool requeue(queue_t *q, void *item);
|
||||
|
||||
/* Remove the last item queued.
|
||||
Return the item or NULL if the queue was empty */
|
||||
void *unqueue(queue_t *q);
|
||||
|
||||
typedef bool queue_matcher_t(void *wanted, void *candidate);
|
||||
|
||||
/* Unqueue the most recently queued item for which `matcher(wanted, candidate)`
|
||||
returns true where `candidate` is an item currently on the queue.
|
||||
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);
|
||||
@@ -0,0 +1,226 @@
|
||||
#include "queue.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FAIL do { \
|
||||
printf("\n*** FAILED at %s line %d\n", __FILE__, __LINE__); \
|
||||
pass = false; \
|
||||
} while (0)
|
||||
|
||||
#define EQUAL(A, B) do { \
|
||||
if ((A) != (B)) \
|
||||
FAIL; \
|
||||
} while (0)
|
||||
|
||||
typedef uint32_t Thing_t; /* actual type doesn't matter */
|
||||
|
||||
static Thing_t things[MAX_QUEUE_SIZE];
|
||||
static Thing_t thing1, thing2;
|
||||
|
||||
static bool matcher(void *wanted, void *candidate)
|
||||
{
|
||||
return wanted == candidate;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool pass = true;
|
||||
queue_t queue;
|
||||
init_queue(&queue);
|
||||
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* queue is full */
|
||||
if (put_queue(&queue, &thing1))
|
||||
FAIL;
|
||||
|
||||
Thing_t *p;
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
|
||||
/* queue is empty */
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, NULL);
|
||||
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[0]);
|
||||
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[1]);
|
||||
|
||||
if (!requeue(&queue, &thing1))
|
||||
FAIL;
|
||||
if (!requeue(&queue, &thing2))
|
||||
FAIL;
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &thing2);
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &thing1);
|
||||
|
||||
if (!requeue(&queue, &things[1]))
|
||||
FAIL;
|
||||
if (!requeue(&queue, &things[0]))
|
||||
FAIL;
|
||||
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE / 2; ++i)
|
||||
{
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
|
||||
for (int i = MAX_QUEUE_SIZE / 2; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
FAIL;
|
||||
}
|
||||
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[MAX_QUEUE_SIZE / 2]);
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[MAX_QUEUE_SIZE / 2 + 1]);
|
||||
|
||||
// ---- unqueue ----
|
||||
|
||||
init_queue(&queue);
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
for (int i = MAX_QUEUE_SIZE; --i >= 0;)
|
||||
{
|
||||
p = unqueue(&queue);
|
||||
EQUAL(p, &things[i]);
|
||||
EQUAL(queue.num_items, i);
|
||||
}
|
||||
EQUAL(queue.num_items, 0);
|
||||
if (!put_queue(&queue, &thing1))
|
||||
FAIL;
|
||||
if (!put_queue(&queue, &thing2))
|
||||
FAIL;
|
||||
EQUAL(queue.num_items, 2);
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &thing1);
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &thing2);
|
||||
|
||||
// ---- unqueue_matching ----
|
||||
|
||||
init_queue(&queue);
|
||||
|
||||
// empty queue
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
EQUAL(queue.num_items, 0);
|
||||
|
||||
// one item in queue
|
||||
if (!put_queue(&queue, &thing1))
|
||||
FAIL;
|
||||
EQUAL(queue.num_items, 1);
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing2);
|
||||
EQUAL(p, NULL);
|
||||
EQUAL(queue.num_items, 1);
|
||||
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ 0, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
EQUAL(queue.num_items, 1);
|
||||
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ 1, matcher, &thing1);
|
||||
EQUAL(p, &thing1);
|
||||
EQUAL(queue.num_items, 0);
|
||||
|
||||
// more max_queue values
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ 0, matcher, &things[MAX_QUEUE_SIZE - 1]);
|
||||
EQUAL(p, NULL);
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ 1, matcher, &things[MAX_QUEUE_SIZE - 1]);
|
||||
EQUAL(p, &things[MAX_QUEUE_SIZE - 1]);
|
||||
EQUAL(queue.num_items, MAX_QUEUE_SIZE - 1);
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ MAX_QUEUE_SIZE - 2, matcher, &things[0]);
|
||||
EQUAL(p, NULL);
|
||||
p = unqueue_matching(&queue, /*max_queue=*/ MAX_QUEUE_SIZE - 1, matcher, &things[0]);
|
||||
EQUAL(p, &things[0]);
|
||||
EQUAL(queue.num_items, MAX_QUEUE_SIZE - 2);
|
||||
|
||||
// fill the queue then remove every other item
|
||||
init_queue(&queue);
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
for (int i = MAX_QUEUE_SIZE - 1; i >= 0; i -= 2)
|
||||
{
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &things[i]);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
EQUAL(queue.num_items, MAX_QUEUE_SIZE / 2);
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; i += 2)
|
||||
{
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
EQUAL(queue.num_items, 0);
|
||||
|
||||
// fill the queue then remove every third item
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (!put_queue(&queue, &things[i]))
|
||||
{
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; i += 3)
|
||||
{
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &things[i]);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
EQUAL(queue.num_items, MAX_QUEUE_SIZE * 2 / 3);
|
||||
p = unqueue_matching(&queue, MAX_QUEUE_SIZE, matcher, &thing1);
|
||||
EQUAL(p, NULL);
|
||||
for (int i = 0; i < MAX_QUEUE_SIZE; ++i)
|
||||
{
|
||||
if (i % 3 == 0)
|
||||
continue;
|
||||
p = get_queue(&queue);
|
||||
EQUAL(p, &things[i]);
|
||||
}
|
||||
EQUAL(queue.num_items, 0);
|
||||
|
||||
if (!pass)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
opts=(
|
||||
-Wall -Werror
|
||||
-Wno-error=int-to-pointer-cast
|
||||
-Wno-int-to-pointer-cast
|
||||
-DUNITTEST
|
||||
)
|
||||
|
||||
set -x
|
||||
|
||||
gcc "${opts[@]}" -fsanitize=address -o queue_test queue_test.c queue.c || exit
|
||||
./queue_test || exit
|
||||
|
||||
gcc "${opts[@]}" -o queue_test queue_test.c queue.c || exit
|
||||
valgrind ./queue_test || exit
|
||||
|
||||
: PASS
|
||||
Reference in New Issue
Block a user