eal: add nanosleep based delay function
Add a new rte_delay_us_sleep() function that uses nanosleep(). This function can be used by applications to not implement their own nanosleep() based callback and by internal DPDK code if CPU non-blocking delay needed. Signed-off-by: Ilya Maximets <i.maximets@samsung.com> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
b9788afec5
commit
a51639cc72
@ -7,9 +7,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <rte_common.h>
|
#include <rte_common.h>
|
||||||
|
#include <rte_compat.h>
|
||||||
#include <rte_log.h>
|
#include <rte_log.h>
|
||||||
#include <rte_cycles.h>
|
#include <rte_cycles.h>
|
||||||
#include <rte_pause.h>
|
#include <rte_pause.h>
|
||||||
@ -31,6 +33,28 @@ rte_delay_us_block(unsigned int us)
|
|||||||
rte_pause();
|
rte_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __rte_experimental
|
||||||
|
rte_delay_us_sleep(unsigned int us)
|
||||||
|
{
|
||||||
|
struct timespec wait[2];
|
||||||
|
int ind = 0;
|
||||||
|
|
||||||
|
wait[0].tv_sec = 0;
|
||||||
|
if (us >= US_PER_S) {
|
||||||
|
wait[0].tv_sec = us / US_PER_S;
|
||||||
|
us -= wait[0].tv_sec * US_PER_S;
|
||||||
|
}
|
||||||
|
wait[0].tv_nsec = 1000 * us;
|
||||||
|
|
||||||
|
while (nanosleep(&wait[ind], &wait[1 - ind]) && errno == EINTR) {
|
||||||
|
/*
|
||||||
|
* Sleep was interrupted. Flip the index, so the 'remainder'
|
||||||
|
* will become the 'request' for a next call.
|
||||||
|
*/
|
||||||
|
ind = 1 - ind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
rte_get_tsc_hz(void)
|
rte_get_tsc_hz(void)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <rte_compat.h>
|
||||||
#include <rte_debug.h>
|
#include <rte_debug.h>
|
||||||
#include <rte_atomic.h>
|
#include <rte_atomic.h>
|
||||||
|
|
||||||
@ -157,6 +158,16 @@ rte_delay_ms(unsigned ms)
|
|||||||
*/
|
*/
|
||||||
void rte_delay_us_block(unsigned int us);
|
void rte_delay_us_block(unsigned int us);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delay function that uses system sleep.
|
||||||
|
* Does not block the CPU core.
|
||||||
|
*
|
||||||
|
* @param us
|
||||||
|
* Number of microseconds to wait.
|
||||||
|
*/
|
||||||
|
void __rte_experimental
|
||||||
|
rte_delay_us_sleep(unsigned int us);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace rte_delay_us with user defined function.
|
* Replace rte_delay_us with user defined function.
|
||||||
*
|
*
|
||||||
|
@ -273,6 +273,7 @@ EXPERIMENTAL {
|
|||||||
rte_class_register;
|
rte_class_register;
|
||||||
rte_class_unregister;
|
rte_class_unregister;
|
||||||
rte_ctrl_thread_create;
|
rte_ctrl_thread_create;
|
||||||
|
rte_delay_us_sleep;
|
||||||
rte_dev_event_callback_process;
|
rte_dev_event_callback_process;
|
||||||
rte_dev_event_callback_register;
|
rte_dev_event_callback_register;
|
||||||
rte_dev_event_callback_unregister;
|
rte_dev_event_callback_unregister;
|
||||||
|
@ -278,6 +278,12 @@
|
|||||||
"Func": default_autotest,
|
"Func": default_autotest,
|
||||||
"Report": None,
|
"Report": None,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "Sleep delay",
|
||||||
|
"Command": "delay_us_sleep_autotest",
|
||||||
|
"Func": default_autotest,
|
||||||
|
"Report": None,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "Rawdev autotest",
|
"Name": "Rawdev autotest",
|
||||||
"Command": "rawdev_autotest",
|
"Command": "rawdev_autotest",
|
||||||
|
@ -149,6 +149,7 @@ test_names = [
|
|||||||
'cryptodev_octeontx_autotest',
|
'cryptodev_octeontx_autotest',
|
||||||
'cycles_autotest',
|
'cycles_autotest',
|
||||||
'debug_autotest',
|
'debug_autotest',
|
||||||
|
'delay_us_sleep_autotest',
|
||||||
'devargs_autotest',
|
'devargs_autotest',
|
||||||
'distributor_autotest',
|
'distributor_autotest',
|
||||||
'distributor_perf_autotest',
|
'distributor_perf_autotest',
|
||||||
|
@ -23,6 +23,30 @@
|
|||||||
* of cycles is correct with regard to the frequency of the timer.
|
* of cycles is correct with regard to the frequency of the timer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_wait_one_second(void)
|
||||||
|
{
|
||||||
|
uint64_t cycles, prev_cycles;
|
||||||
|
uint64_t hz = rte_get_timer_hz();
|
||||||
|
uint64_t max_inc = (hz / 100); /* 10 ms max between 2 reads */
|
||||||
|
|
||||||
|
/* check that waiting 1 second is precise */
|
||||||
|
prev_cycles = rte_get_timer_cycles();
|
||||||
|
rte_delay_us(1000000);
|
||||||
|
cycles = rte_get_timer_cycles();
|
||||||
|
|
||||||
|
if ((uint64_t)(cycles - prev_cycles) > (hz + max_inc)) {
|
||||||
|
printf("delay_us is not accurate: too long\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((uint64_t)(cycles - prev_cycles) < (hz - max_inc)) {
|
||||||
|
printf("delay_us is not accurate: too short\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
test_cycles(void)
|
test_cycles(void)
|
||||||
{
|
{
|
||||||
@ -43,25 +67,24 @@ test_cycles(void)
|
|||||||
prev_cycles = cycles;
|
prev_cycles = cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that waiting 1 second is precise */
|
return check_wait_one_second();
|
||||||
prev_cycles = rte_get_timer_cycles();
|
|
||||||
rte_delay_us(1000000);
|
|
||||||
cycles = rte_get_timer_cycles();
|
|
||||||
|
|
||||||
if ((uint64_t)(cycles - prev_cycles) > (hz + max_inc)) {
|
|
||||||
printf("delay_us is not accurate: too long\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((uint64_t)(cycles - prev_cycles) < (hz - max_inc)) {
|
|
||||||
printf("delay_us is not accurate: too short\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_TEST_COMMAND(cycles_autotest, test_cycles);
|
REGISTER_TEST_COMMAND(cycles_autotest, test_cycles);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One second precision test with rte_delay_us_sleep.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_delay_us_sleep(void)
|
||||||
|
{
|
||||||
|
rte_delay_us_callback_register(rte_delay_us_sleep);
|
||||||
|
return check_wait_one_second();
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_TEST_COMMAND(delay_us_sleep_autotest, test_delay_us_sleep);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rte_delay_us_callback test
|
* rte_delay_us_callback test
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user