[2/2] timer: support EAL functions on Windows
Checks
Commit Message
Implemented the needed Windows eal timer functions.
Signed-off-by: Fady Bader <fady@mellanox.com>
---
lib/librte_eal/common/meson.build | 1 +
lib/librte_eal/windows/eal.c | 6 +++
lib/librte_eal/windows/eal_timer.c | 67 +++++++++++++++++++++++++++++++++
lib/librte_eal/windows/include/rte_os.h | 2 +
lib/librte_eal/windows/meson.build | 1 +
5 files changed, 77 insertions(+)
create mode 100644 lib/librte_eal/windows/eal_timer.c
Comments
On 2020-04-23 17:43 GMT+0300 Fady Bader wrote:
[snip]
> diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c
> new file mode 100644
> index 000000000..73eaff948
> --- /dev/null
> +++ b/lib/librte_eal/windows/eal_timer.c
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright 2020 Mellanox Technologies, Ltd
> + */
> +#include <inttypes.h>
> +#include <time.h>
> +
> +#include <rte_windows.h>
> +#include <rte_common.h>
> +#include <rte_log.h>
> +#include <rte_cycles.h>
> +#include <rte_eal.h>
> +#include <rte_errno.h>
> +
> +/* The frequency of the RDTSC timer resolution */
> +static uint64_t eal_tsc_resolution_hz;
> +
> +void
> +rte_delay_us_sleep(unsigned int us)
> +{
> + LONGLONG ns = us * 1000;
> + HANDLE timer;
> + LARGE_INTEGER liDueTime;
Shouldn't Windows code follow DPDK naming conventions?
> + /* create waitable timer */
> + timer = CreateWaitableTimer(NULL, TRUE, NULL);
> + if(!timer){
Missing spaces. There are more styling issues below that could be detected by
running ./devtools/checkpatches.sh.
> + /* didnt find any better errno val */
> + rte_errno = EINVAL;
> + return;
ENOMEM probably indicates lack of resources better. EINVAL usually implies
wrong arguments to the function. You can also use RTE_WIN32_LOG_ERR() here to
log exact error code on debug level.
> + }
> +
> + /* set us microseconds time for timer */
> + liDueTime.QuadPart = -ns;
Timeout is neither in microseconds, nor in nanoseconds, it's in 100-nanosecond
intervals.
> + if(!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, FALSE)){
> + CloseHandle(timer);
> + /* didnt find any better errno val */
> + rte_errno = EFAULT;
And here, EINVAL is probably better, because result depends on function
argument and this probably will be the most frequent source of errors.
> + return;
> + }
> + /* start wait for timer for us microseconds */
> + WaitForSingleObject(timer, INFINITE);
> + CloseHandle(timer);
> +}
[snip]
> diff --git a/lib/librte_eal/windows/include/rte_os.h b/lib/librte_eal/windows/include/rte_os.h
> index 62805a307..951a14d72 100644
> --- a/lib/librte_eal/windows/include/rte_os.h
> +++ b/lib/librte_eal/windows/include/rte_os.h
> @@ -24,6 +24,8 @@ extern "C" {
> #define PATH_MAX _MAX_PATH
> #endif
>
> +#define sleep(x) Sleep(1000 * x)
It's better to enclose "x" in parentheses or to use inline function.
On 2020-04-23 17:43 GMT+0300 Fady Bader wrote:
> +uint64_t
> +get_tsc_freq(void)
> +{
> + uint64_t tsc_freq;
> + LARGE_INTEGER Frequency;
> +
> + QueryPerformanceFrequency(&Frequency);
> + /*
> + QueryPerformanceFrequency output is in khz.
> + Mulitply by 1K to obtain the true frequency of the CPU (khz -> hz)
> + */
> + tsc_freq = ((uint64_t)Frequency.QuadPart * 1000);
> +
> + return tsc_freq;
> +}
QueryPerformanceFrequency() output is in Hz of TSC, not CPU clock. To get
real time interval from TSC difference, we divide that difference to TSC
frequency with no additional 1000 multiplier.
P.S. Fixed my address in Cc.
@@ -20,6 +20,7 @@ if is_windows
'eal_common_options.c',
'eal_common_tailqs.c',
'eal_common_thread.c',
+ 'eal_common_timer.c',
'malloc_elem.c',
'malloc_heap.c',
'rte_malloc.c',
@@ -400,6 +400,12 @@ rte_eal_init(int argc, char **argv)
return -1;
}
+ if (rte_eal_timer_init() < 0) {
+ rte_eal_init_alert("Cannot init TSC timer");
+ rte_errno = EFAULT;
+ return -1;
+ }
+
eal_thread_init_master(rte_config.master_lcore);
RTE_LCORE_FOREACH_SLAVE(i) {
new file mode 100644
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 Mellanox Technologies, Ltd
+ */
+#include <inttypes.h>
+#include <time.h>
+
+#include <rte_windows.h>
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+
+/* The frequency of the RDTSC timer resolution */
+static uint64_t eal_tsc_resolution_hz;
+
+void
+rte_delay_us_sleep(unsigned int us)
+{
+ LONGLONG ns = us * 1000;
+ HANDLE timer;
+ LARGE_INTEGER liDueTime;
+ /* create waitable timer */
+ timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ if(!timer){
+ /* didnt find any better errno val */
+ rte_errno = EINVAL;
+ return;
+ }
+
+ /* set us microseconds time for timer */
+ liDueTime.QuadPart = -ns;
+ if(!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, FALSE)){
+ CloseHandle(timer);
+ /* didnt find any better errno val */
+ rte_errno = EFAULT;
+ return;
+ }
+ /* start wait for timer for us microseconds */
+ WaitForSingleObject(timer, INFINITE);
+ CloseHandle(timer);
+}
+
+uint64_t
+get_tsc_freq(void)
+{
+ uint64_t tsc_freq;
+ LARGE_INTEGER Frequency;
+
+ QueryPerformanceFrequency(&Frequency);
+ /*
+ QueryPerformanceFrequency output is in khz.
+ Mulitply by 1K to obtain the true frequency of the CPU (khz -> hz)
+ */
+ tsc_freq = ((uint64_t)Frequency.QuadPart * 1000);
+
+ return tsc_freq;
+}
+
+
+int
+rte_eal_timer_init(void)
+{
+ set_tsc_freq();
+ return 0;
+}
+
@@ -24,6 +24,8 @@ extern "C" {
#define PATH_MAX _MAX_PATH
#endif
+#define sleep(x) Sleep(1000 * x)
+
#define strerror_r(a, b, c) strerror_s(b, c, a)
/* strdup is deprecated in Microsoft libc and _strdup is preferred */
@@ -12,6 +12,7 @@ sources += files(
'eal_memory.c',
'eal_mp.c',
'eal_thread.c',
+ 'eal_timer.c',
'getopt.c',
)