[dpdk-dev] [PATCH v3] rte_delay_us can be replaced with user function
From: Jozef Martiniak 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 --- app/test/test_cycles.c | 45 ++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 8 lib/librte_eal/common/eal_common_timer.c | 17 +++- lib/librte_eal/common/include/generic/rte_cycles.h | 24 +++- lib/librte_eal/linuxapp/eal/rte_eal_version.map| 8 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/app/test/test_cycles.c b/app/test/test_cycles.c index f6c043a..f189797 100644 --- a/app/test/test_cycles.c +++ b/app/test/test_cycles.c @@ -90,3 +90,48 @@ test_cycles(void) } 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); diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index a335e04..a06acc1 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -162,3 +162,11 @@ DPDK_16.07 { rte_thread_setname; } DPDK_16.04; + +DPDK_16.11 { + global: + + rte_delay_us_block; + rte_delay_us_callback_register; + +} DPDK_16.07; diff --git a/lib/librte_eal/common/eal_common_timer.c b/lib/librte_eal/common/eal_common_timer.c index c4227cd..7265617 100644 --- a/lib/librte_eal/common/eal_common_timer.c +++ b/lib/librte_eal/common/eal_common_timer.c @@ -47,8 +47,11 @@ /* The frequency of the RDTSC timer resolution */ static uint64_t eal_tsc_resolution_hz; +/* Pointer to user delay function */ +void (*rte_delay_us)(unsigned int) = NULL; + void -rte_delay_us(unsigned us) +rte_delay_us_block(unsigned int us) { const uint64_t start = rte_get_timer_cycles(); 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); 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); +} diff --git a/lib/librte_eal/common/include/generic/rte_cycles.h b/lib/librte_eal/common/include/generic/rte_cycles.h index 8cc21f2..4df5833 100644 --- a/lib/librte_eal/common/include/generic/rte_cycles.h +++ b/lib/librte_eal/common/include/generic/rte_cycles.h @@ -180,15 +180,17 @@ rte_get_timer_hz(void) default: rte_panic("Invalid timer source specified\n"); } } - /** + * * Wait at least us microseconds. + * This function can be replaced with user-defined function. + * @see rte_delay_us_callback_register * * @param us * The number of microseconds to wait. */ void -rte_delay_us(unsigned us); +(*rte_delay_us)(unsigned int us); /** * Wait at least ms milliseconds. @@ -202,4 +204,22 @@ rte_delay_ms(unsigned ms) 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. NULL restores + * buildin block delay function. + */ +void rte_delay_us_callback_register(void(*userfunc)(unsigned int)); + + + #endif /* _RTE_CYCLES_H_ */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index db8c984..db216cc 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -166,3 +166,11 @@ DPDK_16.07 { rte_thread_setname; } DPDK_16.0
[dpdk-dev] [PATCH v3] rte_delay_us can be replaced with user function
From: Jozef Martiniak 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 --- app/test/test_cycles.c | 45 ++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 8 lib/librte_eal/common/eal_common_timer.c | 17 +++- lib/librte_eal/common/include/generic/rte_cycles.h | 22 ++- lib/librte_eal/linuxapp/eal/rte_eal_version.map| 8 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/app/test/test_cycles.c b/app/test/test_cycles.c index f6c043a..f189797 100644 --- a/app/test/test_cycles.c +++ b/app/test/test_cycles.c @@ -90,3 +90,48 @@ test_cycles(void) } 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); diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index a335e04..a06acc1 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -162,3 +162,11 @@ DPDK_16.07 { rte_thread_setname; } DPDK_16.04; + +DPDK_16.11 { + global: + + rte_delay_us_block; + rte_delay_us_callback_register; + +} DPDK_16.07; diff --git a/lib/librte_eal/common/eal_common_timer.c b/lib/librte_eal/common/eal_common_timer.c index c4227cd..7265617 100644 --- a/lib/librte_eal/common/eal_common_timer.c +++ b/lib/librte_eal/common/eal_common_timer.c @@ -47,8 +47,11 @@ /* The frequency of the RDTSC timer resolution */ static uint64_t eal_tsc_resolution_hz; +/* Pointer to user delay function */ +void (*rte_delay_us)(unsigned int) = NULL; + void -rte_delay_us(unsigned us) +rte_delay_us_block(unsigned int us) { const uint64_t start = rte_get_timer_cycles(); 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); 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); +} diff --git a/lib/librte_eal/common/include/generic/rte_cycles.h b/lib/librte_eal/common/include/generic/rte_cycles.h index 8cc21f2..96a2da9 100644 --- a/lib/librte_eal/common/include/generic/rte_cycles.h +++ b/lib/librte_eal/common/include/generic/rte_cycles.h @@ -180,15 +180,16 @@ rte_get_timer_hz(void) default: rte_panic("Invalid timer source specified\n"); } } - /** * Wait at least us microseconds. + * This function can be replaced with user-defined function. + * @see rte_delay_us_callback_register * * @param us * The number of microseconds to wait. */ void -rte_delay_us(unsigned us); +(*rte_delay_us)(unsigned int us); /** * Wait at least ms milliseconds. @@ -202,4 +203,21 @@ rte_delay_ms(unsigned ms) 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_ */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index db8c984..db216cc 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -166,3 +166,11 @@ DPDK_16.07 { rte_thread_setname; } DP
[dpdk-dev] [PATCH] rte_delay_us can be replaced with user function
From: Jozef Martiniak when running single-core, some drivers tend to call rte_delay_us for a long time, and that is causing packet drops. Attached patch introduces 2 new functions: void rte_delay_us_callback_register(void(*userfunc)(unsigned)); void rte_delay_us_callback_unregister(void); First one replaces rte_delay_us with userfunc and second one restores original rte_delay_us. Test user_delay_us is included. Signed-off-by: Jozef Martiniak --- app/test/test_cycles.c | 39 ++ lib/librte_eal/common/eal_common_timer.c | 19 +++ lib/librte_eal/common/include/generic/rte_cycles.h | 13 3 files changed, 71 insertions(+) diff --git a/app/test/test_cycles.c b/app/test/test_cycles.c index f6c043a..2b44a53 100644 --- a/app/test/test_cycles.c +++ b/app/test/test_cycles.c @@ -90,3 +90,42 @@ test_cycles(void) } REGISTER_TEST_COMMAND(cycles_autotest, test_cycles); + +/* + * rte_delay_us_callback test + * + * - check if callback is correctly registered/unregistered + * + */ + +static int pattern; +static void my_rte_delay_us(unsigned us) +{ +pattern += us; +} + +static int +test_user_delay_us(void) +{ +pattern = 0; + +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; + +rte_delay_us_callback_unregister(); + +rte_delay_us(3); +if (pattern != 5) +return -1; + +return 0; +} + +REGISTER_TEST_COMMAND(user_delay_us, test_user_delay_us); diff --git a/lib/librte_eal/common/eal_common_timer.c b/lib/librte_eal/common/eal_common_timer.c index c4227cd..a982562 100644 --- a/lib/librte_eal/common/eal_common_timer.c +++ b/lib/librte_eal/common/eal_common_timer.c @@ -47,9 +47,18 @@ /* The frequency of the RDTSC timer resolution */ static uint64_t eal_tsc_resolution_hz; +/* User function which replaces rte_delay_us function */ +static void (*rte_delay_us_override)(unsigned) = NULL; + void rte_delay_us(unsigned us) { + if (unlikely(rte_delay_us_override != NULL)) + { + rte_delay_us_override(us); + return; + } + const uint64_t start = rte_get_timer_cycles(); const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; while ((rte_get_timer_cycles() - start) < ticks) @@ -84,3 +93,13 @@ set_tsc_freq(void) RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); eal_tsc_resolution_hz = freq; } + +void rte_delay_us_callback_register(void (*userfunc)(unsigned)) +{ +rte_delay_us_override = userfunc; +} + +void rte_delay_us_callback_unregister(void) +{ +rte_delay_us_override = NULL; +} diff --git a/lib/librte_eal/common/include/generic/rte_cycles.h b/lib/librte_eal/common/include/generic/rte_cycles.h index 8cc21f2..274f798 100644 --- a/lib/librte_eal/common/include/generic/rte_cycles.h +++ b/lib/librte_eal/common/include/generic/rte_cycles.h @@ -202,4 +202,17 @@ rte_delay_ms(unsigned ms) rte_delay_us(ms * 1000); } +/** + * Replace rte_delay_us with user defined function. + * + * @param userfunc + * User function which replaces rte_delay_us. + */ +void rte_delay_us_callback_register(void(*userfunc)(unsigned)); + +/** + * Unregister user callback function. Restores original rte_delay_us. + */ +void rte_delay_us_callback_unregister(void); + #endif /* _RTE_CYCLES_H_ */ -- 2.1.4
[dpdk-dev] [PATCH] rte_delay_us can be replaced with user function
From: Jozef Martiniak 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==NULL, build-in blocking delay function is restored. Signed-off-by: Jozef Martiniak --- app/test/test_cycles.c | 45 ++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 7 lib/librte_eal/common/eal_common_timer.c | 22 ++- lib/librte_eal/common/include/generic/rte_cycles.h | 15 +++- lib/librte_eal/linuxapp/eal/rte_eal_version.map| 7 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/app/test/test_cycles.c b/app/test/test_cycles.c index f6c043a..7415ac8 100644 --- a/app/test/test_cycles.c +++ b/app/test/test_cycles.c @@ -90,3 +90,48 @@ test_cycles(void) } REGISTER_TEST_COMMAND(cycles_autotest, test_cycles); + +/* + * rte_delay_us_callback test + * + * - check if callback is correctly registered/unregistered + * + */ + +static int pattern; +static void my_rte_delay_us(unsigned 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(NULL); + +rte_delay_us(3); +if (pattern != 5) +return -1; + +return 0; +} + +REGISTER_TEST_COMMAND(user_delay_us, test_user_delay_us); diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index a335e04..2f83ed0 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -162,3 +162,10 @@ DPDK_16.07 { rte_thread_setname; } DPDK_16.04; + +DPDK_16.11 { + global: + + rte_delay_us_callback_register; + +} DPDK_16.07; diff --git a/lib/librte_eal/common/eal_common_timer.c b/lib/librte_eal/common/eal_common_timer.c index c4227cd..ddfa9d1 100644 --- a/lib/librte_eal/common/eal_common_timer.c +++ b/lib/librte_eal/common/eal_common_timer.c @@ -47,8 +47,11 @@ /* The frequency of the RDTSC timer resolution */ static uint64_t eal_tsc_resolution_hz; -void -rte_delay_us(unsigned us) +/* Pointer to user delay function */ +void (*rte_delay_us)(unsigned) = NULL; + +static void +rte_delay_us_block(unsigned us) { const uint64_t start = rte_get_timer_cycles(); const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; @@ -84,3 +87,18 @@ set_tsc_freq(void) RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); eal_tsc_resolution_hz = freq; } + +void rte_delay_us_callback_register(void (*userfunc)(unsigned)) +{ +if (userfunc == NULL) +rte_delay_us = rte_delay_us_block; +else +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(NULL); +} diff --git a/lib/librte_eal/common/include/generic/rte_cycles.h b/lib/librte_eal/common/include/generic/rte_cycles.h index 8cc21f2..7a45b58 100644 --- a/lib/librte_eal/common/include/generic/rte_cycles.h +++ b/lib/librte_eal/common/include/generic/rte_cycles.h @@ -182,13 +182,16 @@ rte_get_timer_hz(void) } /** + * * Wait at least us microseconds. + * This function can be replaced with user-defined function using + * rte_delay_us_callback_register * * @param us * The number of microseconds to wait. */ void -rte_delay_us(unsigned us); +(*rte_delay_us)(unsigned us); /** * Wait at least ms milliseconds. @@ -202,4 +205,14 @@ rte_delay_ms(unsigned ms) rte_delay_us(ms * 1000); } +/** + * Replace rte_delay_us with user defined function. + * + * @param userfunc + * User function which replaces rte_delay_us. NULL restores + * buildin block delay function. + */ +void rte_delay_us_callback_register(void(*userfunc)(unsigned)); + + #endif /* _RTE_CYCLES_H_ */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index db8c984..4ba30ed 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -166,3 +166,10 @@ DPDK_16.07 { rte_thread_setname; } DPDK_16.04; + +DPDK_16.11 { + global: + + rte_delay_us_callback_register; + +} DPDK_16.07; -- 2.1.4