From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pd0-f181.google.com (mail-pd0-f181.google.com [209.85.192.181]) by dpdk.org (Postfix) with ESMTP id 9E70A5A9D for ; Thu, 9 Apr 2015 21:40:32 +0200 (CEST) Received: by pddn5 with SMTP id n5so163278248pdd.2 for ; Thu, 09 Apr 2015 12:40:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=l9J8tVlhhN+aXi204jSd6YUlwce6RRbcyWz+DnNdrJM=; b=ph0CEBCPAK5sH5Y10e8+hhOZNRIPP8rIMOr2A9HvHg3XHFhVj8PQCRyf3OY5LN3Ihm iXMpwwKH9MxazzOhosED/bby03Gk4OfdDzdjh0QDnvHQtx2xbSgob+8rAFL0Ypn+Ixnn rStUdGeCBlMXy+G7T1c9hTPpsRKMOPY3JL+qjrcfP7/rAvsDIEDFoZui5aXkN58QT63u jnERcZSEqkIiFuRiurJcg0jp0mogFJTX/U2H3RmHVbuatgfwkxGEgIIvc0AHU7eUsn4p gkgHTlGSMncSu9iRZjIrxO4WMkJCIYocFwS+mJm0QlRXFoTLgHC3edVLTspHXha0pzWD Ud/w== X-Received: by 10.68.65.66 with SMTP id v2mr36730684pbs.10.1428608431966; Thu, 09 Apr 2015 12:40:31 -0700 (PDT) Received: from user-PC.hsd1.ca.comcast.net (c-98-234-176-9.hsd1.ca.comcast.net. [98.234.176.9]) by mx.google.com with ESMTPSA id xv9sm15149298pbc.2.2015.04.09.12.40.31 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Apr 2015 12:40:31 -0700 (PDT) From: Ravi Kerur To: dev@dpdk.org Date: Thu, 9 Apr 2015 12:40:08 -0700 Message-Id: <1428608412-31191-3-git-send-email-rkerur@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1428608412-31191-1-git-send-email-rkerur@gmail.com> References: <1428608301-31033-1-git-send-email-rkerur@gmail.com> <1428608412-31191-1-git-send-email-rkerur@gmail.com> Subject: [dpdk-dev] [PATCH v5 2/8] Move common functions in eal.c X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Apr 2015 19:40:33 -0000 Changes in v5 Rebase to latest code. Changes in v4 Remove eal_externs.h file, instead use _get_ and _set_ APIS to access those variables. Split eal_common.c into eal_common_system.c and and eal_common_runtime.c rte_eal prefix functions are moved to _runtime_ and eal prefix functions are moved to _system_ files respectively. Changes in v3 Changed subject to be more explicit on file name inclusion. Changes in v2 In function rte_eal_config_create remove #ifdef _BSDAPP_ and initialize mem_cfg_addr unconditionally. Changes in v1 Move common functions in eal.c to librte_eal/common/eal_common.c. Following functions are moved to eal_common.c file. struct rte_config *rte_eal_get_configuration(void); int eal_parse_sysfs_value(const char *filename, unsigned long *val); static void rte_eal_config_create(void); enum rte_proc_type_t eal_proc_type_detect(void); void rte_eal_config_init(void); rte_usage_hook_t rte_set_application_usage_hook(rte_usage_hook_t usage_func); inline size_t eal_get_hugepage_mem_size(void); void eal_check_mem_on_local_socket(void); int sync_func(__attribute__((unused)) void *arg); inline void rte_eal_mcfg_complete(void); int rte_eal_has_hugepages(void); enum rte_lcore_role_t rte_eal_lcore_role(unsigned lcore_id); enum rte_proc_type_t rte_eal_process_type(void); Makefile changes to reflect new files added. Fix checkpatch warnings and errors. Signed-off-by: Ravi Kerur --- lib/librte_eal/bsdapp/eal/Makefile | 2 + lib/librte_eal/bsdapp/eal/eal.c | 271 ++++---------------------- lib/librte_eal/common/eal_common_runtime.c | 201 ++++++++++++++++++++ lib/librte_eal/common/eal_common_system.c | 203 ++++++++++++++++++++ lib/librte_eal/common/eal_hugepages.h | 1 + lib/librte_eal/common/eal_private.h | 78 ++++++++ lib/librte_eal/common/include/rte_eal.h | 4 + lib/librte_eal/linuxapp/eal/Makefile | 2 + lib/librte_eal/linuxapp/eal/eal.c | 295 ++++------------------------- 9 files changed, 566 insertions(+), 491 deletions(-) create mode 100644 lib/librte_eal/common/eal_common_runtime.c create mode 100644 lib/librte_eal/common/eal_common_system.c diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile index 55971b9..d0a7c43 100644 --- a/lib/librte_eal/bsdapp/eal/Makefile +++ b/lib/librte_eal/bsdapp/eal/Makefile @@ -78,6 +78,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_devargs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_thread.c +SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_system.c +SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_runtime.c CFLAGS_eal.o := -D_GNU_SOURCE #CFLAGS_eal_thread.o := -D_GNU_SOURCE diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c index 871d5f4..721dd32 100644 --- a/lib/librte_eal/bsdapp/eal/eal.c +++ b/lib/librte_eal/bsdapp/eal/eal.c @@ -80,29 +80,6 @@ #include "eal_hugepages.h" #include "eal_options.h" -#define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) - -/* Allow the application to print its usage message too if set */ -static rte_usage_hook_t rte_application_usage_hook = NULL; -/* early configuration structure, when memory config is not mmapped */ -static struct rte_mem_config early_mem_config; - -/* define fd variable here, because file needs to be kept open for the - * duration of the program, as we hold a write lock on it in the primary proc */ -static int mem_cfg_fd = -1; - -static struct flock wr_lock = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = offsetof(struct rte_mem_config, memseg), - .l_len = sizeof(early_mem_config.memseg), -}; - -/* Address of global and public configuration */ -static struct rte_config rte_config = { - .mem_config = &early_mem_config, -}; - /* internal configuration (per-core) */ struct lcore_config lcore_config[RTE_MAX_LCORE]; @@ -112,160 +89,57 @@ struct internal_config internal_config; /* used by rte_rdtsc() */ int rte_cycles_vmware_tsc_map; -/* Return a pointer to the configuration structure */ -struct rte_config * -rte_eal_get_configuration(void) -{ - return &rte_config; -} - -/* parse a sysfs (or other) file containing one integer value */ -int -eal_parse_sysfs_value(const char *filename, unsigned long *val) -{ - FILE *f; - char buf[BUFSIZ]; - char *end = NULL; - - if ((f = fopen(filename, "r")) == NULL) { - RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n", - __func__, filename); - return -1; - } - - if (fgets(buf, sizeof(buf), f) == NULL) { - RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n", - __func__, filename); - fclose(f); - return -1; - } - *val = strtoul(buf, &end, 0); - if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { - RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n", - __func__, filename); - fclose(f); - return -1; - } - fclose(f); - return 0; -} - - -/* create memory configuration in shared/mmap memory. Take out - * a write lock on the memsegs, so we can auto-detect primary/secondary. - * This means we never close the file while running (auto-close on exit). - * We also don't lock the whole file, so that in future we can use read-locks - * on other parts, e.g. memzones, to detect if there are running secondary - * processes. */ -static void -rte_eal_config_create(void) +inline void * +rte_eal_get_mem_cfg_addr(void) { - void *rte_mem_cfg_addr; - int retval; - - const char *pathname = eal_runtime_config_path(); - - if (internal_config.no_shconf) - return; - - if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660); - if (mem_cfg_fd < 0) - rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); - } - - retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config)); - if (retval < 0){ - close(mem_cfg_fd); - rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname); - } - - retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock); - if (retval < 0){ - close(mem_cfg_fd); - rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary " - "process running?\n", pathname); - } - - rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), - PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); - - if (rte_mem_cfg_addr == MAP_FAILED){ - rte_panic("Cannot mmap memory for rte_config\n"); - } - memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); - rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; + return NULL; } /* attach to an existing shared memory config */ -static void +void rte_eal_config_attach(void) { - void *rte_mem_cfg_addr; + struct rte_mem_config *mem_config; + struct rte_config *rte_config; const char *pathname = eal_runtime_config_path(); + int *mem_cfg_fd = eal_get_mem_cfg_fd(); if (internal_config.no_shconf) return; - if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDWR); - if (mem_cfg_fd < 0) + rte_config = rte_eal_get_configuration(); + if (rte_config == NULL) + return; + + if (*mem_cfg_fd < 0) { + *mem_cfg_fd = open(pathname, O_RDWR); + if (*mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } - rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), - PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); - close(mem_cfg_fd); - if (rte_mem_cfg_addr == MAP_FAILED) + mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config), + PROT_READ | PROT_WRITE, + MAP_SHARED, *mem_cfg_fd, 0); + close(*mem_cfg_fd); + if (mem_config == MAP_FAILED) rte_panic("Cannot mmap memory for rte_config\n"); - rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; -} - -/* Detect if we are a primary or a secondary process */ -enum rte_proc_type_t -eal_proc_type_detect(void) -{ - enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; - const char *pathname = eal_runtime_config_path(); - - /* if we can open the file but not get a write-lock we are a secondary - * process. NOTE: if we get a file handle back, we keep that open - * and don't close it to prevent a race condition between multiple opens */ - if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) && - (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) - ptype = RTE_PROC_SECONDARY; - - RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", - ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); - - return ptype; + rte_config->mem_config = mem_config; } -/* Sets up rte_config structure with the pointer to shared memory config.*/ -static void -rte_config_init(void) +/* NOP for BSD */ +void +rte_eal_config_reattach(void) { - rte_config.process_type = internal_config.process_type; - - switch (rte_config.process_type){ - case RTE_PROC_PRIMARY: - rte_eal_config_create(); - break; - case RTE_PROC_SECONDARY: - rte_eal_config_attach(); - rte_eal_mcfg_wait_complete(rte_config.mem_config); - break; - case RTE_PROC_AUTO: - case RTE_PROC_INVALID: - rte_panic("Invalid process type\n"); - } } /* display usage */ static void eal_usage(const char *prgname) { + rte_usage_hook_t rte_application_usage_hook = + rte_get_application_usage_hook(); + printf("\nUsage: %s ", prgname); eal_common_usage(); /* Allow the application to print its usage message too if hook is set */ @@ -275,37 +149,6 @@ eal_usage(const char *prgname) } } -/* Set a per-application usage message */ -rte_usage_hook_t -rte_set_application_usage_hook( rte_usage_hook_t usage_func ) -{ - rte_usage_hook_t old_func; - - /* Will be NULL on the first call to denote the last usage routine. */ - old_func = rte_application_usage_hook; - rte_application_usage_hook = usage_func; - - return old_func; -} - -static inline size_t -eal_get_hugepage_mem_size(void) -{ - uint64_t size = 0; - unsigned i, j; - - for (i = 0; i < internal_config.num_hugepage_sizes; i++) { - struct hugepage_info *hpi = &internal_config.hugepage_info[i]; - if (hpi->hugedir != NULL) { - for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { - size += hpi->hugepage_sz * hpi->num_pages[j]; - } - } - } - - return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; -} - /* Parse the argument given in the command line of the application */ static int eal_parse_args(int argc, char **argv) @@ -378,45 +221,6 @@ eal_parse_args(int argc, char **argv) return ret; } -static void -eal_check_mem_on_local_socket(void) -{ - const struct rte_memseg *ms; - int i, socket_id; - - socket_id = rte_lcore_to_socket_id(rte_config.master_lcore); - - ms = rte_eal_get_physmem_layout(); - - for (i = 0; i < RTE_MAX_MEMSEG; i++) - if (ms[i].socket_id == socket_id && - ms[i].len > 0) - return; - - RTE_LOG(WARNING, EAL, "WARNING: Master core has no " - "memory on local socket!\n"); -} - -static int -sync_func(__attribute__((unused)) void *arg) -{ - return 0; -} - -inline static void -rte_eal_mcfg_complete(void) -{ - /* ALL shared mem_config related INIT DONE */ - if (rte_config.process_type == RTE_PROC_PRIMARY) - rte_config.mem_config->magic = RTE_MAGIC; -} - -/* return non-zero if hugepages are enabled. */ -int rte_eal_has_hugepages(void) -{ - return !internal_config.no_hugetlbfs; -} - /* Abstraction for port I/0 privilege */ int rte_eal_iopl_init(void) @@ -436,9 +240,14 @@ rte_eal_init(int argc, char **argv) { int i, fctret, ret; pthread_t thread_id; + struct rte_config *rte_config; static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0); char cpuset[RTE_CPU_AFFINITY_STR_LEN]; + rte_config = rte_eal_get_configuration(); + if (rte_config == NULL) + return -1; + if (!rte_atomic32_test_and_set(&run_once)) return -1; @@ -512,12 +321,12 @@ rte_eal_init(int argc, char **argv) rte_eal_mcfg_complete(); - eal_thread_init_master(rte_config.master_lcore); + eal_thread_init_master(rte_config->master_lcore); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%p;cpuset=[%s%s])\n", - rte_config.master_lcore, thread_id, cpuset, + rte_config->master_lcore, thread_id, cpuset, ret == 0 ? "" : "..."); if (rte_eal_dev_init() < 0) @@ -556,17 +365,3 @@ rte_eal_init(int argc, char **argv) return fctret; } - -/* get core role */ -enum rte_lcore_role_t -rte_eal_lcore_role(unsigned lcore_id) -{ - return (rte_config.lcore_role[lcore_id]); -} - -enum rte_proc_type_t -rte_eal_process_type(void) -{ - return (rte_config.process_type); -} - diff --git a/lib/librte_eal/common/eal_common_runtime.c b/lib/librte_eal/common/eal_common_runtime.c new file mode 100644 index 0000000..a7ea718 --- /dev/null +++ b/lib/librte_eal/common/eal_common_runtime.c @@ -0,0 +1,201 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2014 6WIND S.A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "eal_private.h" +#include "eal_thread.h" +#include "eal_internal_cfg.h" +#include "eal_filesystem.h" +#include "eal_hugepages.h" +#include "eal_options.h" + +/* Allow the application to print its usage message too if set */ +rte_usage_hook_t rte_application_usage_hook = NULL; + +/* early configuration structure, when memory config is not mmapped */ +static struct rte_mem_config early_mem_config; + +/* Address of global and public configuration */ +struct rte_config rte_config = { + .mem_config = &early_mem_config, +}; + +/* Return a pointer to the configuration structure */ +struct rte_config * +rte_eal_get_configuration(void) +{ + return &rte_config; +} + +/* create memory configuration in shared/mmap memory. Take out + * a write lock on the memsegs, so we can auto-detect primary/secondary. + * This means we never close the file while running (auto-close on exit). + * We also don't lock the whole file, so that in future we can use read-locks + * on other parts, e.g. memzones, to detect if there are running secondary + * processes. */ +static void +rte_eal_config_create(void) +{ + void *rte_mem_cfg_addr; + int retval; + int *mem_cfg_fd = eal_get_mem_cfg_fd(); + + const char *pathname = eal_runtime_config_path(); + + if (internal_config.no_shconf) + return; + + rte_mem_cfg_addr = rte_eal_get_mem_cfg_addr(); + + if (*mem_cfg_fd < 0) { + *mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660); + if (*mem_cfg_fd < 0) + rte_panic("Cannot open '%s' for rte_mem_config\n", + pathname); + } + + retval = eal_ftruncate_and_fcntl(mem_cfg_fd, + sizeof(*rte_config.mem_config)); + + if (retval == -1) { + close(*mem_cfg_fd); + rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname); + } else if (retval == -2) { + close(*mem_cfg_fd); + rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. " + "Is another primary process running?\n", pathname); + } + + rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, + sizeof(*rte_config.mem_config), PROT_READ | PROT_WRITE, + MAP_SHARED, *mem_cfg_fd, 0); + + if (rte_mem_cfg_addr == MAP_FAILED) + rte_panic("Cannot mmap memory for rte_config\n"); + + memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); + rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; + + /* store address of the config in the config itself so that secondary + * processes could later map the config into this exact location + */ + rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr; +} + +/* Sets up rte_config structure with the pointer to shared memory config.*/ +void +rte_config_init(void) +{ + rte_config.process_type = internal_config.process_type; + + switch (rte_config.process_type) { + case RTE_PROC_PRIMARY: + rte_eal_config_create(); + break; + case RTE_PROC_SECONDARY: + rte_eal_config_attach(); + rte_eal_mcfg_wait_complete(rte_config.mem_config); + rte_eal_config_reattach(); + break; + case RTE_PROC_AUTO: + case RTE_PROC_INVALID: + rte_panic("Invalid process type\n"); + } +} + +/* Get per-application usage message */ +rte_usage_hook_t +rte_get_application_usage_hook(void) +{ + return rte_application_usage_hook; +} + +/* Set a per-application usage message */ +rte_usage_hook_t +rte_set_application_usage_hook(rte_usage_hook_t usage_func) +{ + rte_usage_hook_t old_func; + + /* Will be NULL on the first call to denote the last usage routine. */ + old_func = rte_application_usage_hook; + rte_application_usage_hook = usage_func; + + return old_func; +} + +inline void +rte_eal_mcfg_complete(void) +{ + /* ALL shared mem_config related INIT DONE */ + if (rte_config.process_type == RTE_PROC_PRIMARY) + rte_config.mem_config->magic = RTE_MAGIC; +} + +/* return non-zero if hugepages are enabled. */ +int rte_eal_has_hugepages(void) +{ + return !internal_config.no_hugetlbfs; +} + +/* get core role */ +enum rte_lcore_role_t +rte_eal_lcore_role(unsigned lcore_id) +{ + return rte_config.lcore_role[lcore_id]; +} + +enum rte_proc_type_t +rte_eal_process_type(void) +{ + return rte_config.process_type; +} diff --git a/lib/librte_eal/common/eal_common_system.c b/lib/librte_eal/common/eal_common_system.c new file mode 100644 index 0000000..1fd48cc --- /dev/null +++ b/lib/librte_eal/common/eal_common_system.c @@ -0,0 +1,203 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2014 6WIND S.A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "eal_private.h" +#include "eal_thread.h" +#include "eal_internal_cfg.h" +#include "eal_filesystem.h" +#include "eal_hugepages.h" +#include "eal_options.h" + +#include +#include +#include + +/* define fd variable here, because file needs to be kept open for the + * duration of the program, as we hold a write lock on it in the primary proc */ +int mem_cfg_fd = -1; + +static struct flock wr_lock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = offsetof(struct rte_mem_config, memseg), + .l_len = sizeof(((struct rte_mem_config *)0)->memseg), +}; + +/* Return memory config file descriptor */ +int* +eal_get_mem_cfg_fd(void) +{ + return &mem_cfg_fd; +} + +/* parse a sysfs (or other) file containing one integer value */ +int +eal_parse_sysfs_value(const char *filename, unsigned long *val) +{ + FILE *f; + char buf[BUFSIZ]; + char *end = NULL; + + f = fopen(filename, "r"); + if (f == NULL) { + RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n", + __func__, filename); + return -1; + } + + if (fgets(buf, sizeof(buf), f) == NULL) { + RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n", + __func__, filename); + fclose(f); + return -1; + } + *val = strtoul(buf, &end, 0); + if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { + RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n", + __func__, filename); + fclose(f); + return -1; + } + fclose(f); + return 0; +} + +/* Detect if we are a primary or a secondary process */ +enum rte_proc_type_t +eal_proc_type_detect(void) +{ + enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; + const char *pathname = eal_runtime_config_path(); + + /* if we can open the file but not get a write-lock we are + * a secondary process. NOTE: if we get a file handle back, + * we keep that open and don't close it to prevent a race + * condition between multiple opens + */ + mem_cfg_fd = open(pathname, O_RDWR); + if ((mem_cfg_fd >= 0) && + (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) + ptype = RTE_PROC_SECONDARY; + + RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", + ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); + + return ptype; +} + +inline size_t +eal_get_hugepage_mem_size(void) +{ + uint64_t size = 0; + unsigned i, j; + + for (i = 0; i < internal_config.num_hugepage_sizes; i++) { + struct hugepage_info *hpi = &internal_config.hugepage_info[i]; + + if (hpi->hugedir != NULL) { + for (j = 0; j < RTE_MAX_NUMA_NODES; j++) + size += hpi->hugepage_sz * hpi->num_pages[j]; + } + } + + return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; +} + +void +eal_check_mem_on_local_socket(void) +{ + const struct rte_memseg *ms; + int i, socket_id; + struct rte_config *rte_config = + rte_eal_get_configuration(); + + if (rte_config == NULL) { + RTE_LOG(WARNING, EAL, "WARNING: rte_config NULL!\n"); + return; + } + + socket_id = rte_lcore_to_socket_id(rte_config->master_lcore); + + ms = rte_eal_get_physmem_layout(); + + for (i = 0; i < RTE_MAX_MEMSEG; i++) + if (ms[i].socket_id == socket_id && + ms[i].len > 0) + return; + + RTE_LOG(WARNING, EAL, "WARNING: Master core has no " + "memory on local socket!\n"); +} + +int +sync_func(__attribute__((unused)) void *arg) +{ + return 0; +} + +/* + * Perform ftruncate and fcntl operations on + * memory config file descriptor. + */ +int +eal_ftruncate_and_fcntl(int *mem_cfg_fd, size_t size) +{ + int retval; + + retval = ftruncate(*mem_cfg_fd, size); + if (retval < 0) + return -1; + + retval = fcntl(*mem_cfg_fd, F_SETLK, &wr_lock); + if (retval < 0) + return -2; + return 0; +} diff --git a/lib/librte_eal/common/eal_hugepages.h b/lib/librte_eal/common/eal_hugepages.h index 38edac0..0b4d7a2 100644 --- a/lib/librte_eal/common/eal_hugepages.h +++ b/lib/librte_eal/common/eal_hugepages.h @@ -63,5 +63,6 @@ struct hugepage_file { * for the EAL to use */ int eal_hugepage_info_init(void); +inline size_t eal_get_hugepage_mem_size(void); #endif /* EAL_HUGEPAGES_H */ diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 4acf5a0..cdcf4b9 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -36,6 +36,8 @@ #include +#include + /** * Initialize the memzone subsystem (private to eal). * @@ -232,4 +234,80 @@ int rte_eal_dev_init(void); */ int rte_eal_check_module(const char *module_name); +/** + * This function sets up rte_config structure + * + * This function is private to the EAL. + */ +void rte_config_init(void); + +/** + * This function checks memory on local socket(NUMA) + * + * This function is private to the EAL. + */ +void eal_check_mem_on_local_socket(void); + +/** + * This function updates shared mem_config INIT DONE + * + * This function is private to the EAL. + */ +inline void rte_eal_mcfg_complete(void); + +/** + * + * This function is private to the EAL. + */ +int sync_func(__attribute__((unused)) void *arg); + +/** + * + * This function is private to the EAL. + */ +inline void *rte_eal_get_mem_cfg_addr(void); + +/** + * Return a pointer to the configuration structure + * + * This function is private to the EAL. + */ +struct rte_config *rte_eal_get_configuration(void); + +/** + * Return memory config file descriptor + * + * This function is private to the EAL. + */ +int *eal_get_mem_cfg_fd(void); + +/** + * Perform ftruncate and fcntl operations on + * memory config file descriptor. + * + * This function is private to the EAL. + */ +int eal_ftruncate_and_fcntl(int *mem_cfg_fd, size_t size); + +/** + * Get per-application usage message + * + * This function is private to the EAL. + */ +rte_usage_hook_t rte_get_application_usage_hook(void); + +/** + * This function attaches shared memory config + * + * This function is private to the EAL. + */ +void rte_eal_config_attach(void); + +/** + * This function reattaches shared memory config + * + * This function is private to the EAL. + */ +void rte_eal_config_reattach(void); + #endif /* _EAL_PRIVATE_H_ */ diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h index 1385a73..daf2ee0 100644 --- a/lib/librte_eal/common/include/rte_eal.h +++ b/lib/librte_eal/common/include/rte_eal.h @@ -51,6 +51,10 @@ extern "C" { #define RTE_MAGIC 19820526 /**< Magic number written by the main partition when ready. */ +#define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) + +#define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10) + /** * The lcore role (used in RTE or not). */ diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile index 01f7b70..c36d5f4 100644 --- a/lib/librte_eal/linuxapp/eal/Makefile +++ b/lib/librte_eal/linuxapp/eal/Makefile @@ -90,6 +90,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_devargs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_thread.c +SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_system.c +SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_runtime.c CFLAGS_eal.o := -D_GNU_SOURCE CFLAGS_eal_interrupts.o := -D_GNU_SOURCE diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index bd770cf..f6109d9 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -84,13 +84,6 @@ #include "eal_hugepages.h" #include "eal_options.h" -#define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) - -#define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10) - -/* Allow the application to print its usage message too if set */ -static rte_usage_hook_t rte_application_usage_hook = NULL; - TAILQ_HEAD(shared_driver_list, shared_driver); /* Definition for shared object drivers. */ @@ -105,25 +98,6 @@ struct shared_driver { static struct shared_driver_list solib_list = TAILQ_HEAD_INITIALIZER(solib_list); -/* early configuration structure, when memory config is not mmapped */ -static struct rte_mem_config early_mem_config; - -/* define fd variable here, because file needs to be kept open for the - * duration of the program, as we hold a write lock on it in the primary proc */ -static int mem_cfg_fd = -1; - -static struct flock wr_lock = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = offsetof(struct rte_mem_config, memseg), - .l_len = sizeof(early_mem_config.memseg), -}; - -/* Address of global and public configuration */ -static struct rte_config rte_config = { - .mem_config = &early_mem_config, -}; - /* internal configuration (per-core) */ struct lcore_config lcore_config[RTE_MAX_LCORE]; @@ -133,196 +107,85 @@ struct internal_config internal_config; /* used by rte_rdtsc() */ int rte_cycles_vmware_tsc_map; -/* Return a pointer to the configuration structure */ -struct rte_config * -rte_eal_get_configuration(void) -{ - return &rte_config; -} - -/* parse a sysfs (or other) file containing one integer value */ -int -eal_parse_sysfs_value(const char *filename, unsigned long *val) -{ - FILE *f; - char buf[BUFSIZ]; - char *end = NULL; - - if ((f = fopen(filename, "r")) == NULL) { - RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n", - __func__, filename); - return -1; - } - - if (fgets(buf, sizeof(buf), f) == NULL) { - RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n", - __func__, filename); - fclose(f); - return -1; - } - *val = strtoul(buf, &end, 0); - if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { - RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n", - __func__, filename); - fclose(f); - return -1; - } - fclose(f); - return 0; -} - - -/* create memory configuration in shared/mmap memory. Take out - * a write lock on the memsegs, so we can auto-detect primary/secondary. - * This means we never close the file while running (auto-close on exit). - * We also don't lock the whole file, so that in future we can use read-locks - * on other parts, e.g. memzones, to detect if there are running secondary - * processes. */ -static void -rte_eal_config_create(void) +inline void * +rte_eal_get_mem_cfg_addr(void) { - void *rte_mem_cfg_addr; - int retval; - - const char *pathname = eal_runtime_config_path(); - - if (internal_config.no_shconf) - return; + void *mem_cfg_addr; - /* map the config before hugepage address so that we don't waste a page */ if (internal_config.base_virtaddr != 0) - rte_mem_cfg_addr = (void *) + mem_cfg_addr = (void *) RTE_ALIGN_FLOOR(internal_config.base_virtaddr - sizeof(struct rte_mem_config), sysconf(_SC_PAGE_SIZE)); else - rte_mem_cfg_addr = NULL; - - if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660); - if (mem_cfg_fd < 0) - rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); - } - - retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config)); - if (retval < 0){ - close(mem_cfg_fd); - rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname); - } - - retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock); - if (retval < 0){ - close(mem_cfg_fd); - rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary " - "process running?\n", pathname); - } - - rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config), - PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); - - if (rte_mem_cfg_addr == MAP_FAILED){ - rte_panic("Cannot mmap memory for rte_config\n"); - } - memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); - rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; - - /* store address of the config in the config itself so that secondary - * processes could later map the config into this exact location */ - rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr; + mem_cfg_addr = NULL; + return mem_cfg_addr; } /* attach to an existing shared memory config */ -static void +void rte_eal_config_attach(void) { struct rte_mem_config *mem_config; + struct rte_config *rte_config; + int *mem_cfg_fd = eal_get_mem_cfg_fd(); const char *pathname = eal_runtime_config_path(); if (internal_config.no_shconf) return; - if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDWR); - if (mem_cfg_fd < 0) + rte_config = rte_eal_get_configuration(); + if (rte_config == NULL) + return; + + if (*mem_cfg_fd < 0) { + *mem_cfg_fd = open(pathname, O_RDWR); + if (*mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } /* map it as read-only first */ mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config), - PROT_READ, MAP_SHARED, mem_cfg_fd, 0); + PROT_READ, MAP_SHARED, *mem_cfg_fd, 0); if (mem_config == MAP_FAILED) rte_panic("Cannot mmap memory for rte_config\n"); - rte_config.mem_config = mem_config; + rte_config->mem_config = mem_config; } /* reattach the shared config at exact memory location primary process has it */ -static void +void rte_eal_config_reattach(void) { struct rte_mem_config *mem_config; void *rte_mem_cfg_addr; + struct rte_config *rte_config; + int *mem_cfg_fd = eal_get_mem_cfg_fd(); if (internal_config.no_shconf) return; + rte_config = rte_eal_get_configuration(); + if (rte_config == NULL) + return; + /* save the address primary process has mapped shared config to */ - rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr; + rte_mem_cfg_addr = + (void *) (uintptr_t) rte_config->mem_config->mem_cfg_addr; /* unmap original config */ - munmap(rte_config.mem_config, sizeof(struct rte_mem_config)); + munmap(rte_config->mem_config, sizeof(struct rte_mem_config)); /* remap the config at proper address */ mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr, - sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, - mem_cfg_fd, 0); - close(mem_cfg_fd); + sizeof(*mem_config), PROT_READ | PROT_WRITE, + MAP_SHARED, *mem_cfg_fd, 0); + close(*mem_cfg_fd); if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr) rte_panic("Cannot mmap memory for rte_config\n"); - rte_config.mem_config = mem_config; -} - -/* Detect if we are a primary or a secondary process */ -enum rte_proc_type_t -eal_proc_type_detect(void) -{ - enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; - const char *pathname = eal_runtime_config_path(); - - /* if we can open the file but not get a write-lock we are a secondary - * process. NOTE: if we get a file handle back, we keep that open - * and don't close it to prevent a race condition between multiple opens */ - if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) && - (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) - ptype = RTE_PROC_SECONDARY; - - RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", - ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); - - return ptype; -} - -/* Sets up rte_config structure with the pointer to shared memory config.*/ -static void -rte_config_init(void) -{ - rte_config.process_type = internal_config.process_type; - - switch (rte_config.process_type){ - case RTE_PROC_PRIMARY: - rte_eal_config_create(); - break; - case RTE_PROC_SECONDARY: - rte_eal_config_attach(); - rte_eal_mcfg_wait_complete(rte_config.mem_config); - rte_eal_config_reattach(); - break; - case RTE_PROC_AUTO: - case RTE_PROC_INVALID: - rte_panic("Invalid process type\n"); - } + rte_config->mem_config = mem_config; } /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */ @@ -348,6 +211,9 @@ eal_hugedirs_unlock(void) static void eal_usage(const char *prgname) { + rte_usage_hook_t rte_application_usage_hook = + rte_get_application_usage_hook(); + printf("\nUsage: %s ", prgname); eal_common_usage(); printf("EAL Linux options:\n" @@ -367,19 +233,6 @@ eal_usage(const char *prgname) } } -/* Set a per-application usage message */ -rte_usage_hook_t -rte_set_application_usage_hook( rte_usage_hook_t usage_func ) -{ - rte_usage_hook_t old_func; - - /* Will be NULL on the first call to denote the last usage routine. */ - old_func = rte_application_usage_hook; - rte_application_usage_hook = usage_func; - - return old_func; -} - static int eal_parse_socket_mem(char *socket_mem) { @@ -481,24 +334,6 @@ eal_parse_vfio_intr(const char *mode) return -1; } -static inline size_t -eal_get_hugepage_mem_size(void) -{ - uint64_t size = 0; - unsigned i, j; - - for (i = 0; i < internal_config.num_hugepage_sizes; i++) { - struct hugepage_info *hpi = &internal_config.hugepage_info[i]; - if (hpi->hugedir != NULL) { - for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { - size += hpi->hugepage_sz * hpi->num_pages[j]; - } - } - } - - return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; -} - /* Parse the argument given in the command line of the application */ static int eal_parse_args(int argc, char **argv) @@ -645,39 +480,6 @@ eal_parse_args(int argc, char **argv) return ret; } -static void -eal_check_mem_on_local_socket(void) -{ - const struct rte_memseg *ms; - int i, socket_id; - - socket_id = rte_lcore_to_socket_id(rte_config.master_lcore); - - ms = rte_eal_get_physmem_layout(); - - for (i = 0; i < RTE_MAX_MEMSEG; i++) - if (ms[i].socket_id == socket_id && - ms[i].len > 0) - return; - - RTE_LOG(WARNING, EAL, "WARNING: Master core has no " - "memory on local socket!\n"); -} - -static int -sync_func(__attribute__((unused)) void *arg) -{ - return 0; -} - -inline static void -rte_eal_mcfg_complete(void) -{ - /* ALL shared mem_config related INIT DONE */ - if (rte_config.process_type == RTE_PROC_PRIMARY) - rte_config.mem_config->magic = RTE_MAGIC; -} - /* * Request iopl privilege for all RPL, returns 0 on success * iopl() call is mostly for the i386 architecture. For other architectures, @@ -705,6 +507,11 @@ rte_eal_init(int argc, char **argv) struct shared_driver *solib = NULL; const char *logid; char cpuset[RTE_CPU_AFFINITY_STR_LEN]; + struct rte_config *rte_config; + + rte_config = rte_eal_get_configuration(); + if (rte_config == NULL) + return -1; if (!rte_atomic32_test_and_set(&run_once)) return -1; @@ -803,12 +610,12 @@ rte_eal_init(int argc, char **argv) RTE_LOG(WARNING, EAL, "%s\n", dlerror()); } - eal_thread_init_master(rte_config.master_lcore); + eal_thread_init_master(rte_config->master_lcore); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%x;cpuset=[%s%s])\n", - rte_config.master_lcore, (int)thread_id, cpuset, + rte_config->master_lcore, (int)thread_id, cpuset, ret == 0 ? "" : "..."); if (rte_eal_dev_init() < 0) @@ -848,24 +655,6 @@ rte_eal_init(int argc, char **argv) return fctret; } -/* get core role */ -enum rte_lcore_role_t -rte_eal_lcore_role(unsigned lcore_id) -{ - return (rte_config.lcore_role[lcore_id]); -} - -enum rte_proc_type_t -rte_eal_process_type(void) -{ - return (rte_config.process_type); -} - -int rte_eal_has_hugepages(void) -{ - return ! internal_config.no_hugetlbfs; -} - int rte_eal_check_module(const char *module_name) { -- 1.9.1