[2/2] timer: support EAL functions on Windows

Message ID 20200423144350.4016-3-fady@mellanox.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series eal timer split and implementation for Windows |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail apply issues

Commit Message

Fady Bader April 23, 2020, 2:43 p.m. UTC
  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

Dmitry Kozlyuk April 23, 2020, 3:18 p.m. UTC | #1
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.
  
Dmitry Kozlyuk April 24, 2020, 9:32 p.m. UTC | #2
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.
  

Patch

diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 6dcdcc890..532330e6d 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -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',
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 38f17f09c..32853fbac 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.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) {
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;
+	/* 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;
+}
+
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)
+
 #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 0bd56cd8f..769cde797 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -12,6 +12,7 @@  sources += files(
 	'eal_memory.c',
 	'eal_mp.c',
 	'eal_thread.c',
+	'eal_timer.c',
 	'getopt.c',
 )