#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "cm_setup.h"
#include "cm_error_handler.h"
#define APP_EO_NAME "Control EO"
typedef struct app_msg_t {
} app_msg_t;
typedef struct app_shm_t {
em_pool_t pool;
em_queue_t eo_q;
em_timer_t tmr;
unsigned int core_count;
} app_shm_t;
static ENV_LOCAL app_shm_t *app_shm;
#define SECOND_IN_NS 1000000000
static uint64_t timeout = 50000000;
static uint64_t wait_time = 25000000;
static uint64_t resolution = 1000;
static bool no_event_mode;
const struct option longopts[] = {
{"timeout", required_argument, NULL, 't'},
{"wait", required_argument, NULL, 'w'},
{"resolution", required_argument, NULL, 'r'},
{"no-event", no_argument, NULL, 'n'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
const char *shortopts = "t:w:r:nh";
const char *descopts[] = {
"Period for a timeout in ns, default 50ms",
"Wait time in ns, default 25ms",
"Timer resolution in ns, default 1000ns",
"No event mode, no events are sent to the EO",
"Print usage and exit",
NULL
};
const char *instructions =
"The application sets up a periodic timeout for every core and\n"
"waits for a given time upon receiving an event. The wait time\n"
"simulates how long a core handles an event, and the periodic timeout\n"
"sets the frequency at which a core receives events. The wait-time/timeout\n"
"ratio can roughly represent the percentage of time a core is in an active state.\n\n"
"This application provides a reference for the CLI top command.\n"
"\n";
static em_status_t app_eo_start(
void *eo_ctx, em_eo_t eo,
static em_status_t app_eo_start_local(
void *eo_ctx, em_eo_t eo);
static em_status_t app_eo_stop(
void *eo_ctx, em_eo_t eo);
static void app_eo_receive(
void *eo_ctx, em_event_t event,
em_event_type_t type,
em_queue_t queue, void *q_ctx);
static void usage(void)
{
APPL_PRINT("cli_top: simple application with fixed core load\n\n%s", instructions);
for (int i = 0; ; i++) {
if (longopts[i].name == NULL)
break;
APPL_PRINT("-%c or --%-10s %s\n", longopts[i].val, longopts[i].name, descopts[i]);
}
APPL_PRINT("\n");
}
static int parse_args(int first, int argc, char *argv[])
{
optind = first + 1;
while (1) {
int opt;
int long_index;
char *endptr;
int64_t num;
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
if (opt == -1)
break;
switch (opt) {
case 't': {
num = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || num < 0)
return 0;
timeout = (uint64_t)num;
}
break;
case 'w': {
num = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || num < 0)
return 0;
wait_time = (uint64_t)num;
}
break;
case 'r': {
num = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || num < 0)
return 0;
resolution = (uint64_t)num;
}
break;
case 'n':
no_event_mode = true;
break;
case 'h':
default:
opterr = 0;
usage();
return 0;
}
}
optind = 1;
return 1;
}
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--"))
break;
}
if (i < argc) {
if (!parse_args(i, argc, argv))
return 1;
}
return cm_setup(argc, argv);
}
void test_init(const appl_conf_t *appl_conf)
{
(void)appl_conf;
if (core == 0) {
app_shm = env_shared_reserve("TimerAppShMem", sizeof(app_shm_t));
} else {
app_shm = env_shared_lookup("TimerAppShMem");
}
if (app_shm == NULL) {
"init failed on EM-core: %u",
} else if (core == 0) {
memset(app_shm, 0, sizeof(app_shm_t));
}
}
void test_start(const appl_conf_t *appl_conf)
{
em_eo_t eo;
app_msg_t *msg;
em_queue_t queue;
em_event_t event;
if (appl_conf->num_pools >= 1)
app_shm->pool = appl_conf->pools[0];
else
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,
app_shm->pool);
APPL_PRINT("In order to get accurate result, the update rate for cli\n"
"top command must be at least %lu ns\n\n", timeout);
"Undefined application event pool!");
"Not enough queue group (max: %d) to support given number of cores: %u",
app_shm->core_count = appl_conf->core_count;
test_fatal_if(eo ==
EM_EO_UNDEF,
"Failed to create EO!");
if (no_event_mode) {
test_fatal_if(stat !=
EM_OK,
"Failed to start EO!");
return;
}
test_fatal_if(stat !=
EM_OK,
"Timer does not support resolution %u ns", resolution);
strncpy(attr.
name,
"ExampleTimer", EM_TIMER_NAME_LEN);
test_fatal_if(app_shm->tmr ==
EM_TIMER_UNDEF,
"Failed to create timer!");
test_fatal_if(period_ticks < 1, "timer resolution is too low!\n");
test_fatal_if(stat !=
EM_OK,
"Failed to start EO!");
for (uint32_t i = 0; i < appl_conf->core_count; i++) {
"Failed to create queue group!");
test_fatal_if(stat !=
EM_OK,
"Failed to create queue!");
test_fatal_if(tmo ==
EM_TMO_UNDEF,
"Can't allocate tmo!\n");
app_shm->periodic_tmo[i] = tmo;
msg->tmo = app_shm->periodic_tmo[i];
tick_now + start_abs, period_ticks, event);
test_fatal_if(stat !=
EM_OK,
"Can't activate tmo!\n");
}
}
void test_stop(const appl_conf_t *appl_conf)
{
em_eo_t eo;
(void)appl_conf;
APPL_PRINT("%s() on EM-core %d\n", __func__, core);
test_fatal_if(eo ==
EM_EO_UNDEF,
"Could not find EO:%s", APP_EO_NAME);
test_fatal_if(ret !=
EM_OK,
"EO:%" PRI_EO " stop:%" PRI_STAT
"", eo, ret);
test_fatal_if(ret !=
EM_OK,
"EO:%" PRI_EO " delete:%" PRI_STAT
"", eo, ret);
if (no_event_mode)
return;
test_fatal_if(ret !=
EM_OK,
"Timer:%" PRI_TMR " delete:%" PRI_STAT
"",
app_shm->tmr, ret);
}
void test_term(const appl_conf_t *appl_conf)
{
(void)appl_conf;
APPL_PRINT("%s() on EM-core %d\n", __func__, core);
if (app_shm != NULL) {
env_shared_free(app_shm);
app_shm = NULL;
}
}
static em_status_t app_eo_start(
void *eo_ctx, em_eo_t eo,
{
em_timer_t tmr;
int num_timers;
(void)eo;
(void)conf;
(void)eo_ctx;
APPL_PRINT("EO start\n");
if (no_event_mode) {
APPL_PRINT("No event mode enabled\n");
}
APPL_PRINT("System has %d timer(s)\n", num_timers);
APPL_ERROR("Can't get timer info!\n");
}
APPL_PRINT(
"Timer \"%s\" info:\n", attr.
name);
APPL_PRINT(
" -num_tmo: %d\n", attr.
num_tmo);
APPL_PRINT(
" -tick Hz: %" PRIu64
" hz\n",
em_timer_freq(app_shm->tmr));
}
static em_status_t app_eo_start_local(
void *eo_ctx, em_eo_t eo)
{
(void)eo_ctx;
(void)eo;
APPL_PRINT("EO local start\n");
}
static em_status_t app_eo_stop(
void *eo_ctx, em_eo_t eo)
{
(void)eo_ctx;
APPL_PRINT("EO stop\n");
test_fatal_if(ret !=
EM_OK,
"EO remove queue all:%" PRI_STAT
" EO:%" PRI_EO "",
ret, eo);
for (uint32_t i = 0; i < app_shm->core_count; i++) {
}
test_fatal_if(ret !=
EM_OK,
"Remove queue group:%" PRI_STAT
"", ret);
}
}
static void app_eo_receive(void *eo_ctx, em_event_t event,
void *q_ctx)
{
(void)eo_ctx;
(void)queue;
(void)q_ctx;
if (unlikely(appl_shm->exit_flag)) {
return;
}
odp_time_wait_ns(wait_time);
test_fatal_if(ret !=
EM_OK,
"em_tmo_ack():%" PRI_STAT, ret);
}
#define EM_MAX_QUEUE_GROUPS
void em_core_mask_set(int core, em_core_mask_t *mask)
void em_core_mask_zero(em_core_mask_t *mask)
#define EM_TIMER_CLKSRC_DEFAULT
#define EM_QUEUE_GROUP_UNDEF
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_start_local_func_t)(void *eo_ctx, em_eo_t eo)
void(* em_receive_func_t)(void *eo_ctx, em_event_t event, em_event_type_t type, em_queue_t queue, void *q_ctx)
em_status_t(* em_stop_func_t)(void *eo_ctx, em_eo_t eo)
em_eo_t em_eo_find(const char *name)
em_status_t em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf)
em_status_t em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue)
em_status_t(* em_start_func_t)(void *eo_ctx, em_eo_t eo, const em_eo_conf_t *conf)
em_status_t em_eo_stop_sync(em_eo_t eo)
em_status_t em_eo_delete(em_eo_t eo)
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)
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
void em_free(em_event_t event)
void * em_event_pointer(em_event_t event)
em_queue_group_t em_queue_group_create_sync(const char *name, const em_core_mask_t *mask)
em_status_t em_queue_group_delete(em_queue_group_t queue_group, int num_notif, const em_notif_t notif_tbl[])
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)
int em_timer_list(em_timer_t tmr_list[], int max)
uint64_t em_timer_freq(em_timer_t tmr)
em_status_t em_timer_delete(em_timer_t tmr)
em_timer_tick_t em_timer_ns_to_tick(em_timer_t tmr, uint64_t ns)
em_tmo_state_t em_tmo_state(em_tmo_t tmo)
em_tmo_t em_tmo_create(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue)
em_timer_t em_timer_create(const em_timer_attr_t *tmr_attr)
em_status_t em_tmo_delete(em_tmo_t tmo)
em_status_t em_tmo_cancel(em_tmo_t tmo, em_event_t *cur_event)
em_status_t em_tmo_set_periodic(em_tmo_t tmo, em_timer_tick_t start_abs, em_timer_tick_t period, em_event_t tmo_ev)
em_timer_tick_t em_timer_current_tick(em_timer_t tmr)
em_status_t em_timer_attr(em_timer_t tmr, em_timer_attr_t *tmr_attr)
void em_timer_attr_init(em_timer_attr_t *tmr_attr)
em_status_t em_tmo_ack(em_tmo_t tmo, em_event_t next_tmo_ev)
em_status_t em_timer_res_capability(em_timer_res_param_t *res, em_timer_clksrc_t clk_src)
char name[EM_TIMER_NAME_LEN]
em_timer_res_param_t resparam
em_timer_clksrc_t clk_src