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.mil...@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(-)

diff --git a/platform/linux-generic/include/odp_internal.h 
b/platform/linux-generic/include/odp_internal.h
index fd770b5..2b21777 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -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;
diff --git a/platform/linux-generic/odp_system_info.c 
b/platform/linux-generic/odp_system_info.c
index bbe5358..18c61db 100644
--- a/platform/linux-generic/odp_system_info.c
+++ b/platform/linux-generic/odp_system_info.c
@@ -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)
-- 
2.7.4

Reply via email to