eal: customize delay function

When running single-core, some drivers tend to call rte_delay_us for a
long time, and that is causing packet drops.
To avoid this, rte_delay_us can be replaced with user-defined delay
function with:

void rte_delay_us_callback_register(void(*userfunc)(unsigned));

When userfunc==rte_delay_us_block build-in blocking delay function is
restored.

Signed-off-by: Jozef Martiniak <jozmarti@cisco.com>
This commit is contained in:
Jozef Martiniak 2016-09-26 10:35:09 +02:00 committed by Thomas Monjalon
parent 7b3c4f3517
commit b4d63fb622
5 changed files with 97 additions and 3 deletions

View File

@ -90,3 +90,48 @@ test_cycles(void)
} }
REGISTER_TEST_COMMAND(cycles_autotest, test_cycles); REGISTER_TEST_COMMAND(cycles_autotest, test_cycles);
/*
* rte_delay_us_callback test
*
* - check if callback is correctly registered/unregistered
*
*/
static unsigned int pattern;
static void my_rte_delay_us(unsigned int us)
{
pattern += us;
}
static int
test_user_delay_us(void)
{
pattern = 0;
rte_delay_us(2);
if (pattern != 0)
return -1;
/* register custom delay function */
rte_delay_us_callback_register(my_rte_delay_us);
rte_delay_us(2);
if (pattern != 2)
return -1;
rte_delay_us(3);
if (pattern != 5)
return -1;
/* restore original delay function */
rte_delay_us_callback_register(rte_delay_us_block);
rte_delay_us(3);
if (pattern != 5)
return -1;
return 0;
}
REGISTER_TEST_COMMAND(user_delay_us, test_user_delay_us);

View File

@ -162,3 +162,11 @@ DPDK_16.07 {
rte_thread_setname; rte_thread_setname;
} DPDK_16.04; } DPDK_16.04;
DPDK_16.11 {
global:
rte_delay_us_block;
rte_delay_us_callback_register;
} DPDK_16.07;

View File

@ -47,8 +47,11 @@
/* The frequency of the RDTSC timer resolution */ /* The frequency of the RDTSC timer resolution */
static uint64_t eal_tsc_resolution_hz; static uint64_t eal_tsc_resolution_hz;
/* Pointer to user delay function */
void (*rte_delay_us)(unsigned int) = NULL;
void void
rte_delay_us(unsigned us) rte_delay_us_block(unsigned int us)
{ {
const uint64_t start = rte_get_timer_cycles(); const uint64_t start = rte_get_timer_cycles();
const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6;
@ -84,3 +87,15 @@ set_tsc_freq(void)
RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000);
eal_tsc_resolution_hz = freq; eal_tsc_resolution_hz = freq;
} }
void rte_delay_us_callback_register(void (*userfunc)(unsigned int))
{
rte_delay_us = userfunc;
}
static void __attribute__((constructor))
rte_timer_init(void)
{
/* set rte_delay_us_block as a delay function */
rte_delay_us_callback_register(rte_delay_us_block);
}

View File

@ -180,15 +180,16 @@ rte_get_timer_hz(void)
default: rte_panic("Invalid timer source specified\n"); default: rte_panic("Invalid timer source specified\n");
} }
} }
/** /**
* Wait at least us microseconds. * Wait at least us microseconds.
* This function can be replaced with user-defined function.
* @see rte_delay_us_callback_register
* *
* @param us * @param us
* The number of microseconds to wait. * The number of microseconds to wait.
*/ */
void void
rte_delay_us(unsigned us); (*rte_delay_us)(unsigned int us);
/** /**
* Wait at least ms milliseconds. * Wait at least ms milliseconds.
@ -202,4 +203,21 @@ rte_delay_ms(unsigned ms)
rte_delay_us(ms * 1000); rte_delay_us(ms * 1000);
} }
/**
* Blocking delay function.
*
* @param us
* Number of microseconds to wait.
*/
void rte_delay_us_block(unsigned int us);
/**
* Replace rte_delay_us with user defined function.
*
* @param userfunc
* User function which replaces rte_delay_us. rte_delay_us_block restores
* buildin block delay function.
*/
void rte_delay_us_callback_register(void(*userfunc)(unsigned int));
#endif /* _RTE_CYCLES_H_ */ #endif /* _RTE_CYCLES_H_ */

View File

@ -166,3 +166,11 @@ DPDK_16.07 {
rte_thread_setname; rte_thread_setname;
} DPDK_16.04; } DPDK_16.04;
DPDK_16.11 {
global:
rte_delay_us_block;
rte_delay_us_callback_register;
} DPDK_16.07;