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 <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_compat.h>
|
||||
#include <rte_log.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_pause.h>
|
||||
@ -31,6 +33,28 @@ rte_delay_us_block(unsigned int us)
|
||||
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
|
||||
rte_get_tsc_hz(void)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <rte_compat.h>
|
||||
#include <rte_debug.h>
|
||||
#include <rte_atomic.h>
|
||||
|
||||
@ -157,6 +158,16 @@ rte_delay_ms(unsigned ms)
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -273,6 +273,7 @@ EXPERIMENTAL {
|
||||
rte_class_register;
|
||||
rte_class_unregister;
|
||||
rte_ctrl_thread_create;
|
||||
rte_delay_us_sleep;
|
||||
rte_dev_event_callback_process;
|
||||
rte_dev_event_callback_register;
|
||||
rte_dev_event_callback_unregister;
|
||||
|
@ -278,6 +278,12 @@
|
||||
"Func": default_autotest,
|
||||
"Report": None,
|
||||
},
|
||||
{
|
||||
"Name": "Sleep delay",
|
||||
"Command": "delay_us_sleep_autotest",
|
||||
"Func": default_autotest,
|
||||
"Report": None,
|
||||
},
|
||||
{
|
||||
"Name": "Rawdev autotest",
|
||||
"Command": "rawdev_autotest",
|
||||
|
@ -149,6 +149,7 @@ test_names = [
|
||||
'cryptodev_octeontx_autotest',
|
||||
'cycles_autotest',
|
||||
'debug_autotest',
|
||||
'delay_us_sleep_autotest',
|
||||
'devargs_autotest',
|
||||
'distributor_autotest',
|
||||
'distributor_perf_autotest',
|
||||
|
@ -23,6 +23,30 @@
|
||||
* 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
|
||||
test_cycles(void)
|
||||
{
|
||||
@ -43,25 +67,24 @@ test_cycles(void)
|
||||
prev_cycles = cycles;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return check_wait_one_second();
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user