[API-NEXT,v4,08/10] linux-generic: sysinfo: add API to get current CPU frequency

Message ID 1439278439-11386-9-git-send-email-hongbo.zhang@freescale.com
State New
Headers show

Commit Message

hongbo.zhang@freescale.com Aug. 11, 2015, 7:33 a.m.
From: Hongbo Zhang <hongbo.zhang@linaro.org>

Previous CPU frequency API is adapted to return max frequency, now new
APIs are added for getting the current CPU frequency.
odp_cpu_id_hz(int id) returns frequency of the CPU specified by parameter
id, while odp_cpu_hz() returns frequency of the CPU on which the thread
is running.

Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org>
---
 include/odp/api/cpu.h                    | 20 ++++++++++
 platform/linux-generic/odp_system_info.c | 63 ++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

Comments

Ivan Khoronzhuk Sept. 3, 2015, 3:25 p.m. | #1
On 11.08.15 10:33, hongbo.zhang@freescale.com wrote:
> From: Hongbo Zhang <hongbo.zhang@linaro.org>
>
> Previous CPU frequency API is adapted to return max frequency, now new
> APIs are added for getting the current CPU frequency.
> odp_cpu_id_hz(int id) returns frequency of the CPU specified by parameter
> id, while odp_cpu_hz() returns frequency of the CPU on which the thread
> is running.

Just trying to imagine system which has cpufreq governor that dependently on packet rate,
and hence system load, regulate CPU frequency in order to reduce power consumption.

In this case your CPU rate is changing very fast and frequently.
When you get frequency with odp_cpu_hz() it doesn't mean that this freq was
the same a 1ms ago or 1ms after. What the practical use-case for this call.
I see only one variant - simply for some tracing tool, to get imagination how rate
was changed in time for instance.

Could you please explain, where it can be used else? And why we should rely on this call in
proposed use-cases.
Thanks.

>
> Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org>
> ---
>   include/odp/api/cpu.h                    | 20 ++++++++++
>   platform/linux-generic/odp_system_info.c | 63 ++++++++++++++++++++++++++++++++
>   2 files changed, 83 insertions(+)
>
> diff --git a/include/odp/api/cpu.h b/include/odp/api/cpu.h
> index 36bc47f..02b3420 100644
> --- a/include/odp/api/cpu.h
> +++ b/include/odp/api/cpu.h
> @@ -62,6 +62,26 @@ uint64_t odp_cpu_hz_max(void);
>   uint64_t odp_cpu_id_hz_max(int id);
>
>   /**
> + * Current CPU frequency in Hz
> + *
> + * Returns current frequency of this CPU
> + *
> + * @return CPU frequency in Hz
> + */
> +uint64_t odp_cpu_hz(void);
> +
> +/**
> + * Current CPU frequency of a CPU (in Hz)
> + *
> + * Returns current frequency of the specified CPU
> + *
> + * @param id    CPU ID
> + *
> + * @return CPU frequency in Hz
> + */
> +uint64_t odp_cpu_id_hz(int id);
> +
> +/**
>    * CPU model name
>    *
>    * @return Pointer to CPU model name string
> diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c
> index 55516d0..cb5e224 100644
> --- a/platform/linux-generic/odp_system_info.c
> +++ b/platform/linux-generic/odp_system_info.c
> @@ -146,6 +146,42 @@ static int cpuinfo_x86(FILE *file, odp_system_info_t *sysinfo)
>   	return 0;
>   }
>
> +static uint64_t arch_cpu_hz_current(int id)
> +{
> +	char str[1024];
> +	FILE *file;
> +	int cpu;
> +	char *pos;
> +	double mhz = 0.0;
> +
> +	file = fopen("/proc/cpuinfo", "rt");
> +
> +	/* find the correct processor instance */
> +	while (fgets(str, sizeof(str), file) != NULL) {
> +		pos = strstr(str, "processor");
> +		if (pos) {
> +			sscanf(pos, "processor : %d", &cpu);
> +			if (cpu == id)
> +				break;
> +		}
> +	}
> +
> +	/* extract the cpu current speed */
> +	while (fgets(str, sizeof(str), file) != NULL) {
> +		pos = strstr(str, "cpu MHz");
> +		if (pos) {
> +			sscanf(pos, "cpu MHz : %lf", &mhz);
> +			break;
> +		}
> +	}
> +
> +	fclose(file);
> +	if (mhz)
> +		return (uint64_t)(mhz * 1000000.0);
> +
> +	return -1;
> +}
> +
>   #elif defined __arm__ || defined __aarch64__
>
>   static int cpuinfo_arm(FILE *file ODP_UNUSED,
> @@ -154,6 +190,11 @@ odp_system_info_t *sysinfo ODP_UNUSED)
>   	return 0;
>   }
>
> +static uint64_t arch_cpu_hz_current(int id)
> +{
> +	return -1;
> +}
> +
>   #elif defined __OCTEON__
>
>   static int cpuinfo_octeon(FILE *file, odp_system_info_t *sysinfo)
> @@ -196,6 +237,11 @@ static int cpuinfo_octeon(FILE *file, odp_system_info_t *sysinfo)
>   	return 0;
>   }
>
> +static uint64_t arch_cpu_hz_current(int id)
> +{
> +	return -1;
> +}
> +
>   #elif defined __powerpc__
>   static int cpuinfo_powerpc(FILE *file, odp_system_info_t *sysinfo)
>   {
> @@ -237,6 +283,11 @@ static int cpuinfo_powerpc(FILE *file, odp_system_info_t *sysinfo)
>   	return 0;
>   }
>
> +static uint64_t arch_cpu_hz_current(int id)
> +{
> +	return -1;
> +}
> +
>   #else
>   	#error GCC target not found
>   #endif
> @@ -380,6 +431,18 @@ uint64_t odp_cpu_id_hz_max(int id)
>   		return -1;
>   }
>
> +uint64_t odp_cpu_hz(void)
> +{
> +	int id = sched_getcpu();
> +
> +	return arch_cpu_hz_current(id);
> +}
> +
> +uint64_t odp_cpu_id_hz(int id)
> +{
> +	return arch_cpu_hz_current(id);
> +}
> +
>   uint64_t odp_sys_huge_page_size(void)
>   {
>   	return odp_global_data.system_info.huge_page_size;
>

Patch

diff --git a/include/odp/api/cpu.h b/include/odp/api/cpu.h
index 36bc47f..02b3420 100644
--- a/include/odp/api/cpu.h
+++ b/include/odp/api/cpu.h
@@ -62,6 +62,26 @@  uint64_t odp_cpu_hz_max(void);
 uint64_t odp_cpu_id_hz_max(int id);
 
 /**
+ * Current CPU frequency in Hz
+ *
+ * Returns current frequency of this CPU
+ *
+ * @return CPU frequency in Hz
+ */
+uint64_t odp_cpu_hz(void);
+
+/**
+ * Current CPU frequency of a CPU (in Hz)
+ *
+ * Returns current frequency of the specified CPU
+ *
+ * @param id    CPU ID
+ *
+ * @return CPU frequency in Hz
+ */
+uint64_t odp_cpu_id_hz(int id);
+
+/**
  * CPU model name
  *
  * @return Pointer to CPU model name string
diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c
index 55516d0..cb5e224 100644
--- a/platform/linux-generic/odp_system_info.c
+++ b/platform/linux-generic/odp_system_info.c
@@ -146,6 +146,42 @@  static int cpuinfo_x86(FILE *file, odp_system_info_t *sysinfo)
 	return 0;
 }
 
+static uint64_t arch_cpu_hz_current(int id)
+{
+	char str[1024];
+	FILE *file;
+	int cpu;
+	char *pos;
+	double mhz = 0.0;
+
+	file = fopen("/proc/cpuinfo", "rt");
+
+	/* find the correct processor instance */
+	while (fgets(str, sizeof(str), file) != NULL) {
+		pos = strstr(str, "processor");
+		if (pos) {
+			sscanf(pos, "processor : %d", &cpu);
+			if (cpu == id)
+				break;
+		}
+	}
+
+	/* extract the cpu current speed */
+	while (fgets(str, sizeof(str), file) != NULL) {
+		pos = strstr(str, "cpu MHz");
+		if (pos) {
+			sscanf(pos, "cpu MHz : %lf", &mhz);
+			break;
+		}
+	}
+
+	fclose(file);
+	if (mhz)
+		return (uint64_t)(mhz * 1000000.0);
+
+	return -1;
+}
+
 #elif defined __arm__ || defined __aarch64__
 
 static int cpuinfo_arm(FILE *file ODP_UNUSED,
@@ -154,6 +190,11 @@  odp_system_info_t *sysinfo ODP_UNUSED)
 	return 0;
 }
 
+static uint64_t arch_cpu_hz_current(int id)
+{
+	return -1;
+}
+
 #elif defined __OCTEON__
 
 static int cpuinfo_octeon(FILE *file, odp_system_info_t *sysinfo)
@@ -196,6 +237,11 @@  static int cpuinfo_octeon(FILE *file, odp_system_info_t *sysinfo)
 	return 0;
 }
 
+static uint64_t arch_cpu_hz_current(int id)
+{
+	return -1;
+}
+
 #elif defined __powerpc__
 static int cpuinfo_powerpc(FILE *file, odp_system_info_t *sysinfo)
 {
@@ -237,6 +283,11 @@  static int cpuinfo_powerpc(FILE *file, odp_system_info_t *sysinfo)
 	return 0;
 }
 
+static uint64_t arch_cpu_hz_current(int id)
+{
+	return -1;
+}
+
 #else
 	#error GCC target not found
 #endif
@@ -380,6 +431,18 @@  uint64_t odp_cpu_id_hz_max(int id)
 		return -1;
 }
 
+uint64_t odp_cpu_hz(void)
+{
+	int id = sched_getcpu();
+
+	return arch_cpu_hz_current(id);
+}
+
+uint64_t odp_cpu_id_hz(int id)
+{
+	return arch_cpu_hz_current(id);
+}
+
 uint64_t odp_sys_huge_page_size(void)
 {
 	return odp_global_data.system_info.huge_page_size;