This patchset splits OS dependent EAL timer functions and implements them for windows. v2: * fixing styles and correctness errors. v3: * fixing correctness, get_tsc_freq was reimplemented. v4: * rebasing to the new version of "Windows basic memory management" series. * fixing styles and correctness errors. v5: * breaking the dependency on "Windows basic memory management" series. * fixing correctness errors and warnings. v6: * fixing styles and correctness errors. v7: * fixing make errors. v8: * fixing error handling issue. * removed unneded headers. Fady Bader (3): timer: move from common to Unix directory eal: proc type function for Windows timer: support EAL functions on Windows lib/librte_eal/common/eal_common_timer.c | 22 -------- lib/librte_eal/common/meson.build | 1 + lib/librte_eal/freebsd/Makefile | 4 ++ lib/librte_eal/linux/Makefile | 4 ++ lib/librte_eal/meson.build | 4 ++ lib/librte_eal/unix/eal_unix_timer.c | 29 ++++++++++ lib/librte_eal/unix/meson.build | 6 +++ lib/librte_eal/windows/eal.c | 12 +++++ lib/librte_eal/windows/eal_timer.c | 90 ++++++++++++++++++++++++++++++++ lib/librte_eal/windows/include/rte_os.h | 2 + lib/librte_eal/windows/meson.build | 1 + 11 files changed, 153 insertions(+), 22 deletions(-) create mode 100644 lib/librte_eal/unix/eal_unix_timer.c create mode 100644 lib/librte_eal/unix/meson.build create mode 100644 lib/librte_eal/windows/eal_timer.c -- 2.16.1.windows.4
Eal common timer doesn't compile under Windows. Compilation log: error LNK2019: unresolved external symbol nanosleep referenced in function rte_delay_us_sleep error LNK2019: unresolved external symbol get_tsc_freq referenced in function set_tsc_freq error LNK2019: unresolved external symbol sleep referenced in function set_tsc_freq The reason was that some functions called POSIX functions. The solution was to move POSIX dependent functions from common to Unix. Signed-off-by: Fady Bader <fady@mellanox.com> --- lib/librte_eal/common/eal_common_timer.c | 22 ---------------------- lib/librte_eal/freebsd/Makefile | 4 ++++ lib/librte_eal/linux/Makefile | 4 ++++ lib/librte_eal/meson.build | 4 ++++ lib/librte_eal/unix/eal_unix_timer.c | 29 +++++++++++++++++++++++++++++ lib/librte_eal/unix/meson.build | 6 ++++++ 6 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 lib/librte_eal/unix/eal_unix_timer.c create mode 100644 lib/librte_eal/unix/meson.build diff --git a/lib/librte_eal/common/eal_common_timer.c b/lib/librte_eal/common/eal_common_timer.c index fa9ee1b22..71e0bd035 100644 --- a/lib/librte_eal/common/eal_common_timer.c +++ b/lib/librte_eal/common/eal_common_timer.c @@ -35,28 +35,6 @@ rte_delay_us_block(unsigned int us) rte_pause(); } -void -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) { diff --git a/lib/librte_eal/freebsd/Makefile b/lib/librte_eal/freebsd/Makefile index af95386d4..70ea0de41 100644 --- a/lib/librte_eal/freebsd/Makefile +++ b/lib/librte_eal/freebsd/Makefile @@ -8,6 +8,7 @@ LIB = librte_eal.a ARCH_DIR ?= $(RTE_ARCH) VPATH += $(RTE_SDK)/lib/librte_eal/$(ARCH_DIR) VPATH += $(RTE_SDK)/lib/librte_eal/common +VPATH += $(RTE_SDK)/lib/librte_eal/unix CFLAGS += -I$(SRCDIR)/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common @@ -74,6 +75,9 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_service.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_random.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_reciprocal.c +# from unix dir +SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_unix_timer.c + # from arch dir SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_cpuflags.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_hypervisor.c diff --git a/lib/librte_eal/linux/Makefile b/lib/librte_eal/linux/Makefile index 48cc34844..02a0820ac 100644 --- a/lib/librte_eal/linux/Makefile +++ b/lib/librte_eal/linux/Makefile @@ -8,6 +8,7 @@ LIB = librte_eal.a ARCH_DIR ?= $(RTE_ARCH) VPATH += $(RTE_SDK)/lib/librte_eal/$(ARCH_DIR) VPATH += $(RTE_SDK)/lib/librte_eal/common +VPATH += $(RTE_SDK)/lib/librte_eal/unix CFLAGS += -I$(SRCDIR)/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common @@ -81,6 +82,9 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_service.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_random.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_reciprocal.c +# from unix dir +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_unix_timer.c + # from arch dir SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_cpuflags.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_hypervisor.c diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build index e301f4558..8d492897d 100644 --- a/lib/librte_eal/meson.build +++ b/lib/librte_eal/meson.build @@ -6,6 +6,10 @@ subdir('include') subdir('common') +if not is_windows + subdir('unix') +endif + dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1) subdir(exec_env) diff --git a/lib/librte_eal/unix/eal_unix_timer.c b/lib/librte_eal/unix/eal_unix_timer.c new file mode 100644 index 000000000..cc5015910 --- /dev/null +++ b/lib/librte_eal/unix/eal_unix_timer.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Mellanox Technologies, Ltd + */ + +#include <time.h> + +#include <rte_cycles.h> + +void +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; + } +} diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build new file mode 100644 index 000000000..3e43b6d66 --- /dev/null +++ b/lib/librte_eal/unix/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2020 Mellanox Technologies, Ltd + +sources += files( + 'eal_unix_timer.c', +) -- 2.16.1.windows.4
Implementation of rte_proc_type_t for Windows as it is needed for Windows eal timer. Signed-off-by: Fady Bader <fady@mellanox.com> --- lib/librte_eal/windows/eal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index d084606a6..feee91244 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -90,6 +90,12 @@ eal_proc_type_detect(void) return ptype; } +enum rte_proc_type_t +rte_eal_process_type(void) +{ + return rte_config.process_type; +} + /* display usage */ static void eal_usage(const char *prgname) -- 2.16.1.windows.4
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 | 90 +++++++++++++++++++++++++++++++++ lib/librte_eal/windows/include/rte_os.h | 2 + lib/librte_eal/windows/meson.build | 1 + 5 files changed, 100 insertions(+) create mode 100644 lib/librte_eal/windows/eal_timer.c diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build index 55aaeb18e..2a62ef9b1 100644 --- a/lib/librte_eal/common/meson.build +++ b/lib/librte_eal/common/meson.build @@ -14,6 +14,7 @@ if is_windows 'eal_common_log.c', 'eal_common_options.c', 'eal_common_thread.c', + 'eal_common_timer.c', ) subdir_done() endif diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index feee91244..203dfafdb 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -250,6 +250,12 @@ rte_eal_init(int argc, char **argv) if (fctret < 0) exit(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) { diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c new file mode 100644 index 000000000..b0b83fb9b --- /dev/null +++ b/lib/librte_eal/windows/eal_timer.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Mellanox Technologies, Ltd + */ +#include <inttypes.h> + +#include <rte_windows.h> +#include <rte_common.h> +#include <rte_cycles.h> +#include <rte_eal.h> +#include <rte_errno.h> +#include "eal_private.h" + +#define US_PER_SEC 1E6 +#define CYC_PER_10MHZ 1E7 + +void +rte_delay_us_sleep(unsigned int us) +{ + HANDLE timer; + LARGE_INTEGER due_time; + + /* create waitable timer */ + timer = CreateWaitableTimer(NULL, TRUE, NULL); + if (!timer) { + RTE_LOG_WIN32_ERR("CreateWaitableTimer()"); + rte_errno = ENOMEM; + return; + } + + /* + * due_time's uom is 100 ns, multiply by 10 to convert to microseconds + * set us microseconds time for timer + */ + due_time.QuadPart = -((int64_t)us * 10); + if (!SetWaitableTimer(timer, &due_time, 0, NULL, NULL, FALSE)) { + RTE_LOG_WIN32_ERR("SetWaitableTimer()"); + rte_errno = EINVAL; + goto end; + } + /* start wait for timer for us microseconds */ + if (WaitForSingleObject(timer, INFINITE) == WAIT_FAILED) { + RTE_LOG_WIN32_ERR("WaitForSingleObject()"); + rte_errno = EINVAL; + } + +end: + CloseHandle(timer); +} + +uint64_t +get_tsc_freq(void) +{ + LARGE_INTEGER t_start, t_end, elapsed_us; + LARGE_INTEGER frequency; + uint64_t tsc_hz; + uint64_t end, start = rte_get_tsc_cycles(); + + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&t_start); + + rte_delay_us_sleep(US_PER_SEC / 10); /* 1/10 second */ + + if (rte_errno != 0) + return 0; + + QueryPerformanceCounter(&t_end); + end = rte_get_tsc_cycles(); + + elapsed_us.QuadPart = t_end.QuadPart - t_start.QuadPart; + + /* + * To guard against loss-of-precision, convert to microseconds + * *before* dividing by ticks-per-second. + */ + elapsed_us.QuadPart *= US_PER_SEC; + elapsed_us.QuadPart /= frequency.QuadPart; + + double secs = ((double)elapsed_us.QuadPart)/US_PER_SEC; + tsc_hz = (uint64_t)((end - start)/secs); + /* Round up to 10Mhz. 1E7 ~ 10Mhz */ + return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ); +} + + +int +rte_eal_timer_init(void) +{ + set_tsc_freq(); + return 0; +} diff --git a/lib/librte_eal/windows/include/rte_os.h b/lib/librte_eal/windows/include/rte_os.h index 510e39e03..6410b9c2f 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)) + #define strerror_r(a, b, c) strerror_s(b, c, a) /* strdup is deprecated in Microsoft libc and _strdup is preferred */ diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build index adfc8b9b7..9efbe6fd0 100644 --- a/lib/librte_eal/windows/meson.build +++ b/lib/librte_eal/windows/meson.build @@ -9,6 +9,7 @@ sources += files( 'eal_lcore.c', 'eal_log.c', 'eal_thread.c', + 'eal_timer.c', 'fnmatch.c', 'getopt.c', ) -- 2.16.1.windows.4
> Subject: [PATCH v8 0/3] eal timer split and implementation for Windows
>
> This patchset splits OS dependent EAL timer functions and implements them
> for windows.
>
> v2:
> * fixing styles and correctness errors.
> v3:
> * fixing correctness, get_tsc_freq was reimplemented.
> v4:
> * rebasing to the new version of "Windows basic memory management"
> series.
> * fixing styles and correctness errors.
> v5:
> * breaking the dependency on "Windows basic memory management"
> series.
> * fixing correctness errors and warnings.
> v6:
> * fixing styles and correctness errors.
> v7:
> * fixing make errors.
> v8:
> * fixing error handling issue.
> * removed unneded headers.
>
> Fady Bader (3):
> timer: move from common to Unix directory
> eal: proc type function for Windows
> timer: support EAL functions on Windows
>
> lib/librte_eal/common/eal_common_timer.c | 22 --------
> lib/librte_eal/common/meson.build | 1 +
> lib/librte_eal/freebsd/Makefile | 4 ++
> lib/librte_eal/linux/Makefile | 4 ++
> lib/librte_eal/meson.build | 4 ++
> lib/librte_eal/unix/eal_unix_timer.c | 29 ++++++++++
> lib/librte_eal/unix/meson.build | 6 +++
> lib/librte_eal/windows/eal.c | 12 +++++
> lib/librte_eal/windows/eal_timer.c | 90
> ++++++++++++++++++++++++++++++++
> lib/librte_eal/windows/include/rte_os.h | 2 +
> lib/librte_eal/windows/meson.build | 1 +
> 11 files changed, 153 insertions(+), 22 deletions(-) create mode 100644
> lib/librte_eal/unix/eal_unix_timer.c
> create mode 100644 lib/librte_eal/unix/meson.build create mode 100644
> lib/librte_eal/windows/eal_timer.c
>
> --
> 2.16.1.windows.4
Tested-by: Tal Shnaiderman <talshn@mellanox.com>
Reviewed-by: Tal Shnaiderman <talshn@mellanox.com>
14/06/2020 10:43, Fady Bader:
> This patchset splits OS dependent EAL timer functions and implements them for windows.
>
> v2:
> * fixing styles and correctness errors.
> v3:
> * fixing correctness, get_tsc_freq was reimplemented.
> v4:
> * rebasing to the new version of "Windows basic memory management" series.
> * fixing styles and correctness errors.
> v5:
> * breaking the dependency on "Windows basic memory management" series.
> * fixing correctness errors and warnings.
> v6:
> * fixing styles and correctness errors.
> v7:
> * fixing make errors.
> v8:
> * fixing error handling issue.
> * removed unneded headers.
Please use --in-reply-to to keep all versions in the same thread.
14/06/2020 10:43, Fady Bader:
> Implemented the needed Windows eal timer functions.
>
> Signed-off-by: Fady Bader <fady@mellanox.com>
I think there were some acks and tested flags from previous versions
but they are not reported here.
It is blocking the merge.
On Sun, 14 Jun 2020 11:43:45 +0300
Fady Bader <fady@mellanox.com> wrote:
> v8:
> * fixing error handling issue.
> * removed unneded headers.
The patchset now needs a trivial rebase to apply.
Feel free to propagate my previous Tested-by.
--
Dmitry Kozlyuk
On 6/14/2020 1:43 AM, Fady Bader wrote: > 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 | 90 +++++++++++++++++++++++++++++++++ > lib/librte_eal/windows/include/rte_os.h | 2 + > lib/librte_eal/windows/meson.build | 1 + > 5 files changed, 100 insertions(+) > create mode 100644 lib/librte_eal/windows/eal_timer.c > > diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build > index 55aaeb18e..2a62ef9b1 100644 > --- a/lib/librte_eal/common/meson.build > +++ b/lib/librte_eal/common/meson.build > @@ -14,6 +14,7 @@ if is_windows > 'eal_common_log.c', > 'eal_common_options.c', > 'eal_common_thread.c', > + 'eal_common_timer.c', > ) > subdir_done() > endif > diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c > index feee91244..203dfafdb 100644 > --- a/lib/librte_eal/windows/eal.c > +++ b/lib/librte_eal/windows/eal.c > @@ -250,6 +250,12 @@ rte_eal_init(int argc, char **argv) > if (fctret < 0) > exit(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) { > diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c > new file mode 100644 > index 000000000..b0b83fb9b > --- /dev/null > +++ b/lib/librte_eal/windows/eal_timer.c > @@ -0,0 +1,90 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2020 Mellanox Technologies, Ltd > + */ > +#include <inttypes.h> > + > +#include <rte_windows.h> > +#include <rte_common.h> > +#include <rte_cycles.h> > +#include <rte_eal.h> > +#include <rte_errno.h> > +#include "eal_private.h" > + > +#define US_PER_SEC 1E6 > +#define CYC_PER_10MHZ 1E7 > + > +void > +rte_delay_us_sleep(unsigned int us) > +{ > + HANDLE timer; > + LARGE_INTEGER due_time; > + > + /* create waitable timer */ > + timer = CreateWaitableTimer(NULL, TRUE, NULL); > + if (!timer) { > + RTE_LOG_WIN32_ERR("CreateWaitableTimer()"); > + rte_errno = ENOMEM; > + return; > + } > + > + /* > + * due_time's uom is 100 ns, multiply by 10 to convert to microseconds > + * set us microseconds time for timer > + */ > + due_time.QuadPart = -((int64_t)us * 10); > + if (!SetWaitableTimer(timer, &due_time, 0, NULL, NULL, FALSE)) { > + RTE_LOG_WIN32_ERR("SetWaitableTimer()"); > + rte_errno = EINVAL; > + goto end; > + } > + /* start wait for timer for us microseconds */ > + if (WaitForSingleObject(timer, INFINITE) == WAIT_FAILED) { > + RTE_LOG_WIN32_ERR("WaitForSingleObject()"); > + rte_errno = EINVAL; > + } > + > +end: > + CloseHandle(timer); > +} > + > +uint64_t > +get_tsc_freq(void) > +{ > + LARGE_INTEGER t_start, t_end, elapsed_us; > + LARGE_INTEGER frequency; > + uint64_t tsc_hz; > + uint64_t end, start = rte_get_tsc_cycles(); To be more precise, shouldn't we initialize 'start' just before calling QueryPerformanceCounter() for the first time below? > + > + QueryPerformanceFrequency(&frequency); > + QueryPerformanceCounter(&t_start); > + > + rte_delay_us_sleep(US_PER_SEC / 10); /* 1/10 second */ > + > + if (rte_errno != 0) > + return 0; > + > + QueryPerformanceCounter(&t_end); > + end = rte_get_tsc_cycles(); > + > + elapsed_us.QuadPart = t_end.QuadPart - t_start.QuadPart; > + > + /* > + * To guard against loss-of-precision, convert to microseconds > + * *before* dividing by ticks-per-second. > + */ > + elapsed_us.QuadPart *= US_PER_SEC; > + elapsed_us.QuadPart /= frequency.QuadPart; > + > + double secs = ((double)elapsed_us.QuadPart)/US_PER_SEC; > + tsc_hz = (uint64_t)((end - start)/secs); Please leave a blank like here. > + /* Round up to 10Mhz. 1E7 ~ 10Mhz */ > + return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ); > +} > + > + > +int > +rte_eal_timer_init(void) > +{ > + set_tsc_freq(); > + return 0; > +} > diff --git a/lib/librte_eal/windows/include/rte_os.h b/lib/librte_eal/windows/include/rte_os.h > index 510e39e03..6410b9c2f 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)) > + > #define strerror_r(a, b, c) strerror_s(b, c, a) > > /* strdup is deprecated in Microsoft libc and _strdup is preferred */ > diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build > index adfc8b9b7..9efbe6fd0 100644 > --- a/lib/librte_eal/windows/meson.build > +++ b/lib/librte_eal/windows/meson.build > @@ -9,6 +9,7 @@ sources += files( > 'eal_lcore.c', > 'eal_log.c', > 'eal_thread.c', > + 'eal_timer.c', > 'fnmatch.c', > 'getopt.c', > ) ranjit m.
Sending a new version soon. > Subject: Re: [PATCH v8 3/3] timer: support EAL functions on Windows > > > On 6/14/2020 1:43 AM, Fady Bader wrote: > > 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 | 90 > +++++++++++++++++++++++++++++++++ > > lib/librte_eal/windows/include/rte_os.h | 2 + > > lib/librte_eal/windows/meson.build | 1 + > > 5 files changed, 100 insertions(+) > > create mode 100644 lib/librte_eal/windows/eal_timer.c > > > > diff --git a/lib/librte_eal/common/meson.build > > b/lib/librte_eal/common/meson.build > > index 55aaeb18e..2a62ef9b1 100644 > > --- a/lib/librte_eal/common/meson.build > > +++ b/lib/librte_eal/common/meson.build > > @@ -14,6 +14,7 @@ if is_windows > > 'eal_common_log.c', > > 'eal_common_options.c', > > 'eal_common_thread.c', > > + 'eal_common_timer.c', > > ) > > subdir_done() > > endif > > diff --git a/lib/librte_eal/windows/eal.c > > b/lib/librte_eal/windows/eal.c index feee91244..203dfafdb 100644 > > --- a/lib/librte_eal/windows/eal.c > > +++ b/lib/librte_eal/windows/eal.c > > @@ -250,6 +250,12 @@ rte_eal_init(int argc, char **argv) > > if (fctret < 0) > > exit(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) { > > diff --git a/lib/librte_eal/windows/eal_timer.c > > b/lib/librte_eal/windows/eal_timer.c > > new file mode 100644 > > index 000000000..b0b83fb9b > > --- /dev/null > > +++ b/lib/librte_eal/windows/eal_timer.c > > @@ -0,0 +1,90 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright 2020 Mellanox Technologies, Ltd */ #include > > +<inttypes.h> > > + > > +#include <rte_windows.h> > > +#include <rte_common.h> > > +#include <rte_cycles.h> > > +#include <rte_eal.h> > > +#include <rte_errno.h> > > +#include "eal_private.h" > > + > > +#define US_PER_SEC 1E6 > > +#define CYC_PER_10MHZ 1E7 > > + > > +void > > +rte_delay_us_sleep(unsigned int us) > > +{ > > + HANDLE timer; > > + LARGE_INTEGER due_time; > > + > > + /* create waitable timer */ > > + timer = CreateWaitableTimer(NULL, TRUE, NULL); > > + if (!timer) { > > + RTE_LOG_WIN32_ERR("CreateWaitableTimer()"); > > + rte_errno = ENOMEM; > > + return; > > + } > > + > > + /* > > + * due_time's uom is 100 ns, multiply by 10 to convert to microseconds > > + * set us microseconds time for timer > > + */ > > + due_time.QuadPart = -((int64_t)us * 10); > > + if (!SetWaitableTimer(timer, &due_time, 0, NULL, NULL, FALSE)) { > > + RTE_LOG_WIN32_ERR("SetWaitableTimer()"); > > + rte_errno = EINVAL; > > + goto end; > > + } > > + /* start wait for timer for us microseconds */ > > + if (WaitForSingleObject(timer, INFINITE) == WAIT_FAILED) { > > + RTE_LOG_WIN32_ERR("WaitForSingleObject()"); > > + rte_errno = EINVAL; > > + } > > + > > +end: > > + CloseHandle(timer); > > +} > > + > > +uint64_t > > +get_tsc_freq(void) > > +{ > > + LARGE_INTEGER t_start, t_end, elapsed_us; > > + LARGE_INTEGER frequency; > > + uint64_t tsc_hz; > > + uint64_t end, start = rte_get_tsc_cycles(); > To be more precise, shouldn't we initialize 'start' just before calling > QueryPerformanceCounter() for the first time below? You are right, I'll change it. > > + > > + QueryPerformanceFrequency(&frequency); > > + QueryPerformanceCounter(&t_start); > > + > > + rte_delay_us_sleep(US_PER_SEC / 10); /* 1/10 second */ > > + > > + if (rte_errno != 0) > > + return 0; > > + > > + QueryPerformanceCounter(&t_end); > > + end = rte_get_tsc_cycles(); > > + > > + elapsed_us.QuadPart = t_end.QuadPart - t_start.QuadPart; > > + > > + /* > > + * To guard against loss-of-precision, convert to microseconds > > + * *before* dividing by ticks-per-second. > > + */ > > + elapsed_us.QuadPart *= US_PER_SEC; > > + elapsed_us.QuadPart /= frequency.QuadPart; > > + > > + double secs = ((double)elapsed_us.QuadPart)/US_PER_SEC; > > + tsc_hz = (uint64_t)((end - start)/secs); > Please leave a blank like here. Ok. > > + /* Round up to 10Mhz. 1E7 ~ 10Mhz */ > > + return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ); } > > + > > + > > +int > > +rte_eal_timer_init(void) > > +{ > > + set_tsc_freq(); > > + return 0; > > +} > > diff --git a/lib/librte_eal/windows/include/rte_os.h > > b/lib/librte_eal/windows/include/rte_os.h > > index 510e39e03..6410b9c2f 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)) > > + > > #define strerror_r(a, b, c) strerror_s(b, c, a) > > > > /* strdup is deprecated in Microsoft libc and _strdup is preferred > > */ diff --git a/lib/librte_eal/windows/meson.build > > b/lib/librte_eal/windows/meson.build > > index adfc8b9b7..9efbe6fd0 100644 > > --- a/lib/librte_eal/windows/meson.build > > +++ b/lib/librte_eal/windows/meson.build > > @@ -9,6 +9,7 @@ sources += files( > > 'eal_lcore.c', > > 'eal_log.c', > > 'eal_thread.c', > > + 'eal_timer.c', > > 'fnmatch.c', > > 'getopt.c', > > ) > > > ranjit m. Fady.