@@ -30,7 +30,6 @@ extern __thread int __odp_errno;
typedef struct {
uint64_t cpu_hz_max[MAX_CPU_NUMBER];
- uint64_t default_huge_page_size;
uint64_t page_size;
int cache_line_size;
int cpu_count;
@@ -38,11 +37,17 @@ typedef struct {
char model_str[MAX_CPU_NUMBER][128];
} system_info_t;
+typedef struct {
+ uint64_t default_huge_page_size;
+ char *default_huge_page_dir;
+} hugepage_info_t;
+
struct odp_global_data_s {
pid_t main_pid;
odp_log_func_t log_fn;
odp_abort_func_t abort_fn;
system_info_t system_info;
+ hugepage_info_t hugepage_info;
odp_cpumask_t control_cpus;
odp_cpumask_t worker_cpus;
int num_cpus_installed;
@@ -4,6 +4,13 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+/*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ */
+
#include <odp_posix_extensions.h>
#include <odp/api/system_info.h>
@@ -11,11 +18,13 @@
#include <odp_debug_internal.h>
#include <odp/api/align.h>
#include <odp/api/cpu.h>
+#include <errno.h>
#include <pthread.h>
#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
+#include <ctype.h>
/* sysconf */
#include <unistd.h>
@@ -97,6 +106,158 @@ static uint64_t default_huge_page_size(void)
}
/*
+ * split string into tokens. largely "inspired" by dpdk:
+ * lib/librte_eal/common/eal_common_string_fns.c: rte_strsplit
+ */
+static int strsplit(char *string, int stringlen,
+ char **tokens, int maxtokens, char delim)
+{
+ int i, tok = 0;
+ int tokstart = 1; /* first token is right at start of string */
+
+ if (string == NULL || tokens == NULL)
+ return -1;
+
+ for (i = 0; i < stringlen; i++) {
+ if (string[i] == '\0' || tok >= maxtokens)
+ break;
+ if (tokstart) {
+ tokstart = 0;
+ tokens[tok++] = &string[i];
+ }
+ if (string[i] == delim) {
+ string[i] = '\0';
+ tokstart = 1;
+ }
+ }
+ return tok;
+}
+
+/*
+ * Converts a numeric string to the equivalent uint64_t value.
+ * As well as straight number conversion, also recognises the suffixes
+ * k, m and g for kilobytes, megabytes and gigabytes respectively.
+ *
+ * If a negative number is passed in i.e. a string with the first non-black
+ * character being "-", zero is returned. Zero is also returned in the case of
+ * an error with the strtoull call in the function.
+ * largely "inspired" by dpdk:
+ * lib/librte_eal/common/include/rte_common.h: rte_str_to_size
+ *
+ * param str
+ * String containing number to convert.
+ * return
+ * Number.
+ */
+static inline uint64_t str_to_size(const char *str)
+{
+ char *endptr;
+ unsigned long long size;
+
+ while (isspace((int)*str))
+ str++;
+ if (*str == '-')
+ return 0;
+
+ errno = 0;
+ size = strtoull(str, &endptr, 0);
+ if (errno)
+ return 0;
+
+ if (*endptr == ' ')
+ endptr++; /* allow 1 space gap */
+
+ switch (*endptr) {
+ case 'G':
+ case 'g':
+ size *= 1024; /* fall-through */
+ case 'M':
+ case 'm':
+ size *= 1024; /* fall-through */
+ case 'K':
+ case 'k':
+ size *= 1024; /* fall-through */
+ default:
+ break;
+ }
+ return size;
+}
+
+/*
+ * returns a malloced string containing the name of the directory for
+ * huge pages of a given size (0 for default)
+ * largely "inspired" by dpdk:
+ * lib/librte_eal/linuxapp/eal/eal_hugepage_info.c: get_hugepage_dir
+ *
+ * Analysis of /proc/mounts
+ */
+static char *get_hugepage_dir(uint64_t hugepage_sz)
+{
+ enum proc_mount_fieldnames {
+ DEVICE = 0,
+ MOUNTPT,
+ FSTYPE,
+ OPTIONS,
+ _FIELDNAME_MAX
+ };
+ static uint64_t default_size;
+ const char proc_mounts[] = "/proc/mounts";
+ const char hugetlbfs_str[] = "hugetlbfs";
+ const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
+ const char pagesize_opt[] = "pagesize=";
+ const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
+ const char split_tok = ' ';
+ char *tokens[_FIELDNAME_MAX];
+ char buf[BUFSIZ];
+ char *retval = NULL;
+ const char *pagesz_str;
+ uint64_t pagesz;
+ FILE *fd = fopen(proc_mounts, "r");
+
+ if (fd == NULL)
+ return NULL;
+
+ if (default_size == 0)
+ default_size = default_huge_page_size();
+
+ if (hugepage_sz == 0)
+ hugepage_sz = default_size;
+
+ while (fgets(buf, sizeof(buf), fd)) {
+ if (strsplit(buf, sizeof(buf), tokens,
+ _FIELDNAME_MAX, split_tok) != _FIELDNAME_MAX) {
+ ODP_ERR("Error parsing %s\n", proc_mounts);
+ break; /* return NULL */
+ }
+
+ /* is this hugetlbfs? */
+ if (!strncmp(tokens[FSTYPE], hugetlbfs_str, htlbfs_str_len)) {
+ pagesz_str = strstr(tokens[OPTIONS], pagesize_opt);
+
+ /* No explicit size, default page size is compared */
+ if (pagesz_str == NULL) {
+ if (hugepage_sz == default_size) {
+ retval = strdup(tokens[MOUNTPT]);
+ break;
+ }
+ }
+ /* there is an explicit page size, so check it */
+ else {
+ pagesz =
+ str_to_size(&pagesz_str[pagesize_opt_len]);
+ if (pagesz == hugepage_sz) {
+ retval = strdup(tokens[MOUNTPT]);
+ break;
+ }
+ }
+ } /* end if strncmp hugetlbfs */
+ } /* end while fgets */
+
+ fclose(fd);
+ return retval;
+}
+
+/*
* Analysis of /sys/devices/system/cpu/ files
*/
static int systemcpu(system_info_t *sysinfo)
@@ -125,11 +286,21 @@ static int systemcpu(system_info_t *sysinfo)
return -1;
}
- sysinfo->default_huge_page_size = default_huge_page_size();
-
return 0;
}
+/*
+ * Huge page information
+ */
+static int system_hp(hugepage_info_t *hugeinfo)
+{
+ hugeinfo->default_huge_page_size = default_huge_page_size();
+
+ /* default_huge_page_dir may be NULL if no huge page support */
+ hugeinfo->default_huge_page_dir = get_hugepage_dir(0);
+
+ return 0;
+}
/*
* System info initialisation
@@ -157,6 +328,8 @@ int odp_system_info_init(void)
return -1;
}
+ system_hp(&odp_global_data.hugepage_info);
+
return 0;
}
@@ -165,6 +338,8 @@ int odp_system_info_init(void)
*/
int odp_system_info_term(void)
{
+ free(odp_global_data.hugepage_info.default_huge_page_dir);
+
return 0;
}
@@ -200,7 +375,7 @@ uint64_t odp_cpu_hz_max_id(int id)
uint64_t odp_sys_huge_page_size(void)
{
- return odp_global_data.system_info.default_huge_page_size;
+ return odp_global_data.hugepage_info.default_huge_page_size;
}
uint64_t odp_sys_page_size(void)
The Huge page information is separated and a function to get the huge page mount directory is added. This function is called at init so the information is available later on. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> --- platform/linux-generic/include/odp_internal.h | 7 +- platform/linux-generic/odp_system_info.c | 181 +++++++++++++++++++++++++- 2 files changed, 184 insertions(+), 4 deletions(-) -- 2.7.4