#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <odp_api.h>
#include "cm_setup.h"
#include "cm_error_handler.h"
typedef struct {
unsigned int seq;
} event_types_event_t;
typedef struct {
em_eo_t this_eo;
em_queue_t queue_atomic;
em_queue_t queue_parallel;
em_queue_t queue_ordered;
em_queue_t queue_unsched;
em_queue_t queue_local;
em_atomic_group_t atomic_group;
em_queue_t queue_agrp1;
em_queue_t queue_agrp2;
em_queue_t queue_output;
} my_eo_context_t;
typedef struct {
my_eo_context_t *eo_ctx;
} my_output_fn_args_t;
typedef struct {
odp_pool_t ml_pool;
odp_pool_t dma_pool;
em_pool_t pool_sw;
em_pool_t pool_pkt;
em_atomic_group_t atomic_group;
my_eo_context_t eo_context[2];
} event_types_shm_t;
COMPILE_TIME_ASSERT((sizeof(event_types_shm_t) % ENV_CACHE_LINE_SIZE) == 0,
EVENT_TYPES_SHM_T__SIZE_ERROR);
static ENV_LOCAL event_types_shm_t *event_types_shm;
static void eo_single_receive(void *eo_ctx, em_event_t event,
static void eo_multi_receive(void *eo_ctx, em_event_t events[], int num,
em_queue_t queue, void *q_ctx);
static int output_queue_fn(const em_event_t events[], const unsigned int num,
const em_queue_t output_queue, void *output_fn_args);
int main(int argc, char *argv[])
{
return cm_setup(argc, argv);
}
void test_init(const appl_conf_t *appl_conf)
{
(void)appl_conf;
if (core == 0) {
event_types_shm = env_shared_reserve("Event_typesSharedMem",
sizeof(event_types_shm_t));
} else {
event_types_shm = env_shared_lookup("Event_typesSharedMem");
}
if (event_types_shm == NULL) {
"event_types init failed on EM-core: %u",
} else if (core == 0) {
memset(event_types_shm, 0, sizeof(event_types_shm_t));
}
}
void test_start(const appl_conf_t *appl_conf)
{
em_eo_t eo_a;
em_eo_t eo_b;
odp_ml_compl_pool_param_t ml_pool_params;
odp_pool_t ml_pool;
odp_dma_pool_param_t dma_pool_params;
odp_pool_t dma_pool;
em_pool_t pool1;
if (appl_conf->num_pools >= 1)
pool1 = appl_conf->pools[0];
else
test_fatal_if(status !=
EM_OK,
"Pool info fails, pool:%" PRI_POOL " status:%" PRI_STAT
"",
pool1, status);
em_pool_t pool2;
event_types_shm->pool_sw = pool1;
} else {
event_types_shm->pool_pkt = pool1;
}
test_fatal_if(pool2 ==
EM_POOL_UNDEF,
"Pool-2 creation failed!");
event_types_shm->pool_sw = pool2;
else
event_types_shm->pool_pkt = pool2;
APPL_PRINT("\n"
"***********************************************************\n"
"EM APPLICATION: '%s' initializing:\n"
" %s: %s() - EM-core:%d\n"
" Application running on %u EM-cores (procs:%u, threads:%u)\n"
"***********************************************************\n"
"\n",
appl_conf->name, NO_PATH(__FILE__), __func__,
em_core_id(),
appl_conf->core_count, appl_conf->num_procs, appl_conf->num_threads);
odp_ml_capability_t capa_ml;
int rv;
rv = odp_ml_capability(&capa_ml);
if (rv != 0)
APPL_EXIT_FAILURE("odp_ml_capability() did not succeed");
if (capa_ml.pool.max_num > 0) {
odp_ml_compl_pool_param_init(&ml_pool_params);
ml_pool_params.num = 100;
ml_pool = odp_ml_compl_pool_create("MLComplPool", &ml_pool_params);
if (ml_pool == ODP_POOL_INVALID)
APPL_EXIT_FAILURE("ODP MLcompl pool create failed");
event_types_shm->ml_pool = ml_pool;
} else {
APPL_PRINT("ODP MLcompl pool not supported\n");
event_types_shm->ml_pool = ODP_POOL_INVALID;
}
odp_dma_capability_t capa_dma;
rv = odp_dma_capability(&capa_dma);
if (rv != 0)
APPL_EXIT_FAILURE("odp_dma_capability() did not succeed");
if (capa_dma.pool.max_num > 0) {
odp_dma_pool_param_init(&dma_pool_params);
dma_pool_params.num = 100;
dma_pool = odp_dma_pool_create("DMAComplPool", &dma_pool_params);
if (dma_pool == ODP_POOL_INVALID)
APPL_EXIT_FAILURE("ODP DMAcompl pool create failed");
event_types_shm->dma_pool = dma_pool;
} else {
APPL_PRINT("ODP DMAcompl pool not supported\n");
event_types_shm->dma_pool = ODP_POOL_INVALID;
}
event_types_shm->atomic_group = atomic_group;
eo_stop, NULL,
eo_single_receive, &event_types_shm->eo_context[0]);
test_fatal_if(eo_a ==
EM_EO_UNDEF,
"EO A creation failed!");
event_types_shm->eo_context[0].this_eo = eo_a;
"EO A start:%" PRI_STAT " %" PRI_STAT "",
ret, start_ret);
eo_param.
start = eo_start;
eo_param.
eo_ctx = &event_types_shm->eo_context[1];
test_fatal_if(eo_b ==
EM_EO_UNDEF,
"EO B creation failed!");
event_types_shm->eo_context[1].this_eo = eo_b;
"EO B start:%" PRI_STAT " %" PRI_STAT "",
ret, start_ret);
}
void test_stop(const appl_conf_t *appl_conf)
{
em_eo_t eo_a = event_types_shm->eo_context[0].this_eo;
em_eo_t eo_b = event_types_shm->eo_context[1].this_eo;
em_atomic_group_t atomic_group = event_types_shm->atomic_group;
int err;
(void)appl_conf;
APPL_PRINT("%s() on EM-core %d\n", __func__, core);
APPL_EXIT_FAILURE("EO A stop failed!");
APPL_EXIT_FAILURE("EO B stop failed!");
APPL_EXIT_FAILURE("Atomic group delete failed!");
if (event_types_shm->ml_pool != ODP_POOL_INVALID) {
err = odp_pool_destroy(event_types_shm->ml_pool);
if (err)
APPL_EXIT_FAILURE("ODP ML-completion pool destroy failed!");
}
if (event_types_shm->dma_pool != ODP_POOL_INVALID) {
err = odp_pool_destroy(event_types_shm->dma_pool);
if (err)
APPL_EXIT_FAILURE("ODP DMA-completion pool destroy failed!");
}
APPL_EXIT_FAILURE("Pool-2 delete failed!");
APPL_EXIT_FAILURE("Pool-2 delete failed!");
}
void test_term(const appl_conf_t *appl_conf)
{
(void)appl_conf;
APPL_PRINT("%s() on EM-core %d\n", __func__, core);
if (core == 0) {
env_shared_free(event_types_shm);
}
}
{
my_eo_context_t *eo_ctx = eo_ctx_;
const char *queue_name;
em_queue_t queue_atomic;
em_queue_t queue_parallel;
em_queue_t queue_ordered;
em_queue_t queue_unsched;
em_queue_t queue_local;
em_queue_t queue_agrp1;
em_queue_t queue_agrp2;
em_queue_t queue_output;
(void)conf;
em_eo_get_name(eo, eo_ctx->name, sizeof(eo_ctx->name));
queue_name = "queue-atomic";
test_fatal_if(queue_atomic ==
EM_QUEUE_UNDEF,
"%s creation failed!", queue_name);
queue_name = "queue-parallel";
test_fatal_if(queue_parallel ==
EM_QUEUE_UNDEF,
"%s creation failed!", queue_name);
queue_name = "queue-ordered";
test_fatal_if(queue_ordered ==
EM_QUEUE_UNDEF,
"%s creation failed!", queue_name);
test_fatal_if(status !=
EM_OK,
"EO add queue:%" PRI_STAT
"\n"
test_fatal_if(status !=
EM_OK,
"EO add queue:%" PRI_STAT
"\n"
test_fatal_if(status !=
EM_OK,
"EO add queue:%" PRI_STAT
"\n"
queue_name = "queue-unscheduled";
test_fatal_if(queue_unsched ==
EM_QUEUE_UNDEF,
"%s creation failed!", queue_name);
queue_name = "queue-local";
test_fatal_if(queue_local ==
EM_QUEUE_UNDEF,
"%s creation failed!", queue_name);
test_fatal_if(status !=
EM_OK,
"EO add queue:%" PRI_STAT
"\n"
em_atomic_group_t atomic_group = event_types_shm->atomic_group;
test_fatal_if(queue_agrp1 ==
EM_QUEUE_UNDEF,
"Queue-agrp1 creation failed!");
test_fatal_if(queue_agrp2 ==
EM_QUEUE_UNDEF,
"Queue-agrp2 creation failed!");
test_fatal_if(status !=
EM_OK,
"EO add queue-agrp1:%" PRI_STAT
"\n"
test_fatal_if(status !=
EM_OK,
"EO add queue-agrp2:%" PRI_STAT
"\n"
my_output_fn_args_t output_args;
memset(&queue_conf, 0, sizeof(queue_conf));
memset(&output_conf, 0, sizeof(output_conf));
queue_conf.
conf_len =
sizeof(output_conf);
queue_conf.
conf = &output_conf;
output_args.eo_ctx = eo_ctx;
output_conf.
args_len =
sizeof(output_args);
&queue_conf);
test_fatal_if(queue_output ==
EM_QUEUE_UNDEF,
"Queue-output creation failed!");
eo_ctx->queue_atomic = queue_atomic;
eo_ctx->queue_parallel = queue_parallel;
eo_ctx->queue_ordered = queue_ordered;
eo_ctx->queue_unsched = queue_unsched;
eo_ctx->queue_local = queue_local;
eo_ctx->queue_agrp1 = queue_agrp1;
eo_ctx->queue_agrp2 = queue_agrp2;
eo_ctx->queue_output = queue_output;
if (event_types_shm->ml_pool != ODP_POOL_INVALID) {
odp_ml_compl_t mlcompl;
mlcompl = odp_ml_compl_alloc(event_types_shm->ml_pool);
test_fatal_if(mlcompl == ODP_ML_COMPL_INVALID, "odp_ml_compl_alloc() failed!\n");
APPL_PRINT("%s: ML event allocated!\n", eo_ctx->name);
em_event_t mlcomp_event;
status =
em_send(mlcomp_event, eo_ctx->queue_atomic);
test_fatal_if(status !=
EM_OK,
"em_send():%" PRI_STAT
"\n"
status, eo, eo_ctx->queue_atomic);
APPL_PRINT("%s: ML event sent!\n", eo_ctx->name);
}
if (event_types_shm->dma_pool != ODP_POOL_INVALID) {
odp_dma_compl_t dmacompl;
dmacompl = odp_dma_compl_alloc(event_types_shm->dma_pool);
APPL_PRINT("%s: DMA event allocated!\n", eo_ctx->name);
em_event_t dmacomp_event;
status =
em_send(dmacomp_event, eo_ctx->queue_atomic);
test_fatal_if(status !=
EM_OK,
"em_send():%" PRI_STAT
"\n"
status, eo, eo_ctx->queue_atomic);
APPL_PRINT("%s: DMA event sent!\n", eo_ctx->name);
}
em_event_t event;
event_types_event_t *test_event;
event_types_shm->pool_sw);
test_event->seq = 0;
status =
em_send(event, eo_ctx->queue_atomic);
test_fatal_if(status !=
EM_OK,
"em_send():%" PRI_STAT
"\n"
status, eo, eo_ctx->queue_atomic);
APPL_PRINT("%s: SW event sent!\n", eo_ctx->name);
event_types_shm->pool_pkt);
test_event->seq = 0;
status =
em_send(event, eo_ctx->queue_atomic);
test_fatal_if(status !=
EM_OK,
"em_send():%" PRI_STAT
"\n"
status, eo, eo_ctx->queue_atomic);
APPL_PRINT("%s: PACKET event sent!\n", eo_ctx->name);
}
{
my_eo_context_t *eo_ctx = eo_ctx_;
APPL_PRINT(
"event_types stop on EM-core %d (%s, eo id %" PRI_EO ")\n",
APPL_EXIT_FAILURE("EO remove queue all sync failed!");
APPL_EXIT_FAILURE("Unsched queue delete failed!");
APPL_EXIT_FAILURE("Output queue delete failed!");
APPL_EXIT_FAILURE("EO delete failed!");
return stat;
}
static void eo_single_receive(
void *eo_ctx_, em_event_t event,
em_event_type_t type,
em_queue_t queue, void *q_ctx)
{
my_eo_context_t *eo_ctx = eo_ctx_;
(void)type;
(void)q_ctx;
const char *queue_info = "";
bool is_scheduled = true;
if (unlikely(appl_shm->exit_flag)) {
return;
}
if (queue == eo_ctx->queue_atomic) {
queue_info = "atomic";
queue_next = eo_ctx->queue_parallel;
} else if (queue == eo_ctx->queue_parallel) {
queue_info = "parallel";
queue_next = eo_ctx->queue_ordered;
} else if (queue == eo_ctx->queue_ordered) {
queue_info = "ordered";
queue_next = eo_ctx->queue_agrp1;
} else if (queue == eo_ctx->queue_agrp1) {
queue_info = "agrp:Q1";
queue_next = eo_ctx->queue_agrp2;
} else if (queue == eo_ctx->queue_agrp2) {
queue_info = "agrp:Q2";
queue_next = eo_ctx->queue_local;
is_scheduled = false;
} else if (queue == eo_ctx->queue_local) {
queue_info = "local";
queue_next = eo_ctx->queue_output;
is_scheduled = false;
} else {
"%s(): Unknown Q:%" PRI_QUEUE "", __func__, queue);
}
switch (major_type) {
odp_event_type_t odp_type = odp_event_type(odp_event);
if (odp_type == ODP_EVENT_ML_COMPL) {
printf(
"EM-core%02d, %s: Event from Q:%" PRI_QUEUE "(%s):\tODP ML COMPL\n",
core, eo_ctx->name, queue, queue_info);
} else if (odp_type == ODP_EVENT_DMA_COMPL) {
printf(
"EM-core%02d, %s: Event from Q:%" PRI_QUEUE "(%s):\tODP DMA COMPL\n",
core, eo_ctx->name, queue, queue_info);
} else {
"Unexpected ODP event type: %u", odp_type);
}
break;
}
printf(
"EM-core%02d, %s: Event from Q:%" PRI_QUEUE "(%s):\tEM SW event\n",
core, eo_ctx->name, queue, queue_info);
break;
printf(
"EM-core%02d, %s: Event from Q:%" PRI_QUEUE "(%s):\tEM PACKET event\n",
core, eo_ctx->name, queue, queue_info);
break;
default:
"Unexpected EM event type: %u", event_type);
}
em_queue_t queue_unsched = eo_ctx->queue_unsched;
status =
em_send(event, queue_unsched);
test_fatal_if(status !=
EM_OK,
"em_send():%" PRI_STAT " to unscheduled queue failed!\n"
status, eo_ctx->this_eo, queue_unsched);
odp_time_wait_ns(ODP_TIME_SEC_IN_NS / 10);
"em_queue_dequeue() from unscheduled queue failed!");
if (is_scheduled) {
test_fatal_if(status !=
EM_OK,
"em_event_mark_send():%" PRI_STAT " failed!\n"
status, eo_ctx->this_eo, queue_next);
test_fatal_if(status !=
EM_OK,
"em_event_unmark_send():%" PRI_STAT " failed!\n"
"EO:%" PRI_EO "", status, eo_ctx->this_eo);
}
status =
em_send(event_deq, queue_next);
if (unlikely(status !=
EM_OK)) {
test_fatal_if(!appl_shm->exit_flag,
"em_send():%" PRI_STAT "\n"
status, eo_ctx->this_eo, queue_next);
}
}
}
static void eo_multi_receive(void *eo_ctx_, em_event_t events[], int num,
em_queue_t queue, void *q_ctx)
{
for (int i = 0; i < num; i++) {
em_event_t event = events[i];
eo_single_receive(eo_ctx_, event, type, queue, q_ctx);
}
}
static int output_queue_fn(const em_event_t events[], const unsigned int num,
const em_queue_t output_queue, void *output_fn_args)
{
(void)events;
(void)num;
(void)output_queue;
my_output_fn_args_t *output_args = (my_output_fn_args_t *)output_fn_args;
my_eo_context_t *eo_ctx = output_args->eo_ctx;
printf(
"EM-core%02d, %s: Event from Q:%" PRI_QUEUE "(output)\n",
return sent;
}
#define EM_EO_MULTIRCV_MAX_EVENTS
#define EM_QUEUE_GROUP_DEFAULT
#define EM_QUEUE_GROUP_UNDEF
#define EM_ATOMIC_GROUP_UNDEF
em_queue_t em_queue_create_ag(const char *name, em_queue_prio_t prio, em_atomic_group_t atomic_group, const em_queue_conf_t *conf)
em_status_t em_atomic_group_delete(em_atomic_group_t atomic_group)
em_atomic_group_t em_atomic_group_create(const char *name, em_queue_group_t queue_group)
em_status_t em_eo_remove_queue_all_sync(em_eo_t eo, int delete_queues)
em_eo_t em_eo_create(const char *name, em_start_func_t start, em_start_local_func_t local_start, em_stop_func_t stop, em_stop_local_func_t local_stop, em_receive_func_t receive, const void *eo_ctx)
em_status_t em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf)
void em_eo_multircv_param_init(em_eo_multircv_param_t *param)
em_status_t em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue)
em_status_t em_eo_stop_sync(em_eo_t eo)
em_status_t em_eo_delete(em_eo_t eo)
em_eo_t em_eo_create_multircv(const char *name, const em_eo_multircv_param_t *param)
em_status_t em_unregister_error_handler(void)
#define EM_ERROR_SET_FATAL(error)
em_status_t em_register_error_handler(em_error_handler_t handler)
int em_send_multi(const em_event_t events[], int num, em_queue_t queue)
void em_event_mark_free(em_event_t event)
Mark the event as "free".
em_status_t em_event_unmark_send(em_event_t event)
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
void em_event_unmark_free(em_event_t event)
Unmark an event previously marked as "free" (i.e mark as "allocated" again).
void em_event_mark_free_multi(const em_event_t events[], int num)
Mark multiple events as "free".
void em_event_unmark_free_multi(const em_event_t events[], int num)
Unmark multiple events previously marked as "free".
em_status_t em_event_mark_send(em_event_t event, em_queue_t queue)
em_status_t em_send(em_event_t event, em_queue_t queue)
void em_free(em_event_t event)
void * em_event_pointer(em_event_t event)
odp_event_t em_odp_event2odp(em_event_t event)
uint32_t em_odp_event_hdr_size(void)
em_event_t em_odp_event2em(odp_event_t odp_event)
em_pool_t em_pool_create(const char *name, em_pool_t pool, const em_pool_cfg_t *pool_cfg)
void em_pool_cfg_init(em_pool_cfg_t *const pool_cfg)
em_status_t em_pool_info(em_pool_t pool, em_pool_info_t *pool_info)
em_status_t em_pool_delete(em_pool_t pool)
em_event_t em_queue_dequeue(em_queue_t queue)
em_status_t em_queue_delete(em_queue_t queue)
#define EM_QUEUE_PRIO_UNDEF
#define EM_QUEUE_FLAG_DEFAULT
em_queue_t em_queue_create(const char *name, em_queue_type_t type, em_queue_prio_t prio, em_queue_group_t group, const em_queue_conf_t *conf)
@ EM_QUEUE_TYPE_UNSCHEDULED
em_start_local_func_t local_start
em_receive_multi_func_t receive_multi
em_output_func_t output_fn
struct em_pool_cfg_t::@23 subpool[EM_MAX_SUBPOOLS]
em_event_type_t event_type
em_event_type_t event_type