From: Intel Date: Wed, 19 Dec 2012 23:00:00 +0000 (+0100) Subject: memory: fix for multi process support X-Git-Tag: spdx-start~11384 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=916e4f4f4e;p=dpdk.git memory: fix for multi process support Signed-off-by: Intel --- diff --git a/app/test/test_spinlock.c b/app/test/test_spinlock.c index 16036a96a2..841d17a293 100644 --- a/app/test/test_spinlock.c +++ b/app/test/test_spinlock.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ #include #include #include +#include #include "test.h" @@ -80,7 +82,9 @@ static rte_spinlock_t sl, sl_try; static rte_spinlock_t sl_tab[RTE_MAX_LCORE]; static rte_spinlock_recursive_t slr; -static unsigned count; +static unsigned count = 0; + +static rte_atomic32_t synchro; static int test_spinlock_per_core(__attribute__((unused)) void *arg) @@ -126,60 +130,77 @@ test_spinlock_recursive_per_core(__attribute__((unused)) void *arg) return 0; } -static volatile int count1, count2; static rte_spinlock_t lk = RTE_SPINLOCK_INITIALIZER; -static unsigned int max = 10000000; /* 10M */ -static volatile uint64_t looptime[RTE_MAX_LCORE]; +static uint64_t lock_count[RTE_MAX_LCORE] = {0}; + +#define TIME_S 5 static int -load_loop_fn(__attribute__((unused)) void *dummy) +load_loop_fn(void *func_param) { - uint64_t end, begin; + uint64_t time_diff = 0, begin; + uint64_t hz = rte_get_hpet_hz(); + uint64_t lcount = 0; + const int use_lock = *(int*)func_param; + const unsigned lcore = rte_lcore_id(); + + /* wait synchro for slaves */ + if (lcore != rte_get_master_lcore()) + while (rte_atomic32_read(&synchro) == 0); + begin = rte_get_hpet_cycles(); - unsigned int i = 0; - for ( i = 0; i < max; i++) { - rte_spinlock_lock(&lk); - count1++; - rte_spinlock_unlock(&lk); - count2++; + while (time_diff / hz < TIME_S) { + if (use_lock) + rte_spinlock_lock(&lk); + lcount++; + if (use_lock) + rte_spinlock_unlock(&lk); + /* delay to make lock duty cycle slighlty realistic */ + rte_delay_us(1); + time_diff = rte_get_hpet_cycles() - begin; } - end = rte_get_hpet_cycles(); - looptime[rte_lcore_id()] = end - begin; + lock_count[lcore] = lcount; return 0; } static int -test_spinlock_load(void) +test_spinlock_perf(void) { - if (rte_lcore_count()<= 1) { - printf("no cores counted\n"); - return -1; - } - printf ("Running %u tests.......\n", max); - printf ("Number of cores = %u\n", rte_lcore_count()); + unsigned int i; + uint64_t total = 0; + int lock = 0; + const unsigned lcore = rte_lcore_id(); - rte_eal_mp_remote_launch(load_loop_fn, NULL , CALL_MASTER); - rte_eal_mp_wait_lcore(); + printf("\nTest with no lock on single core...\n"); + load_loop_fn(&lock); + printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]); + memset(lock_count, 0, sizeof(lock_count)); - unsigned int k = 0; - uint64_t avgtime = 0; + printf("\nTest with lock on single core...\n"); + lock = 1; + load_loop_fn(&lock); + printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]); + memset(lock_count, 0, sizeof(lock_count)); - RTE_LCORE_FOREACH(k) { - printf("Core [%u] time = %"PRIu64"\n", k, looptime[k]); - avgtime += looptime[k]; - } + printf("\nTest with lock on %u cores...\n", rte_lcore_count()); - avgtime = avgtime / rte_lcore_count(); - printf("Average time = %"PRIu64"\n", avgtime); + /* Clear synchro and start slaves */ + rte_atomic32_set(&synchro, 0); + rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER); - int check = 0; - check = max * rte_lcore_count(); - if (count1 == check && count2 != check) - printf("Passed Load test\n"); - else { - printf("Failed load test\n"); - return -1; + /* start synchro and launch test on master */ + rte_atomic32_set(&synchro, 1); + load_loop_fn(&lock); + + rte_eal_mp_wait_lcore(); + + RTE_LCORE_FOREACH(i) { + printf("Core [%u] count = %"PRIu64"\n", i, lock_count[i]); + total += lock_count[i]; } + + printf("Total count = %"PRIu64"\n", total); + return 0; } @@ -246,9 +267,6 @@ test_spinlock(void) rte_eal_mp_wait_lcore(); - if (test_spinlock_load()<0) - return -1; - rte_spinlock_recursive_lock(&slr); /* @@ -313,5 +331,8 @@ test_spinlock(void) rte_spinlock_recursive_unlock(&slr); rte_spinlock_recursive_unlock(&slr); + if (test_spinlock_perf() < 0) + return -1; + return ret; } diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c index 76553f66df..c150705bed 100644 --- a/lib/librte_eal/common/eal_common_memory.c +++ b/lib/librte_eal/common/eal_common_memory.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "eal_private.h" @@ -93,12 +94,18 @@ rte_dump_physmem_layout(void) for (i=0; imemseg[i].addr == NULL) break; - printf("phys:0x%"PRIx64", len:0x%"PRIx64", virt:%p, " - "socket_id:%"PRId32"\n", + + printf("Segment %o: phys:0x%"PRIx64", len:0x%"PRIx64", " + "virt:%p, socket_id:%"PRId32", " + "hugepage_sz:0x%"PRIx64", nchannel:%"PRIx32", " + "nrank:%"PRIx32"\n", i, mcfg->memseg[i].phys_addr, mcfg->memseg[i].len, mcfg->memseg[i].addr, - mcfg->memseg[i].socket_id); + mcfg->memseg[i].socket_id, + mcfg->memseg[i].hugepage_sz, + mcfg->memseg[i].nchannel, + mcfg->memseg[i].nrank); } } diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c index df707bfea8..bcdd95e203 100644 --- a/lib/librte_eal/common/eal_common_memzone.c +++ b/lib/librte_eal/common/eal_common_memzone.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -54,10 +55,28 @@ #include "eal_private.h" /* internal copy of free memory segments */ -static struct rte_memseg free_memseg[RTE_MAX_MEMSEG]; +static struct rte_memseg *free_memseg = NULL; -/* pointer to last reserved memzone */ -static unsigned memzone_idx; +static inline const struct rte_memzone * +memzone_lookup_thread_unsafe(const char *name) +{ + const struct rte_mem_config *mcfg; + unsigned i = 0; + + /* get pointer to global configuration */ + mcfg = rte_eal_get_configuration()->mem_config; + + /* + * the algorithm is not optimal (linear), but there are few + * zones and this function should be called at init only + */ + for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) { + if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE)) + return &mcfg->memzone[i]; + } + + return NULL; +} /* * Return a pointer to a correctly filled memzone descriptor. If the @@ -71,60 +90,30 @@ rte_memzone_reserve(const char *name, uint64_t len, int socket_id, len, socket_id, flags, CACHE_LINE_SIZE); } -/* - * Return a pointer to a correctly filled memzone descriptor (with a - * specified alignment). If the allocation cannot be done, return NULL. - */ -const struct rte_memzone * -rte_memzone_reserve_aligned(const char *name, uint64_t len, +static const struct rte_memzone * +memzone_reserve_aligned_thread_unsafe(const char *name, uint64_t len, int socket_id, unsigned flags, unsigned align) { - struct rte_config *config; + struct rte_mem_config *mcfg; unsigned i = 0; int memseg_idx = -1; - uint64_t requested_len; + uint64_t addr_offset, requested_len; uint64_t memseg_len = 0; phys_addr_t memseg_physaddr; void *memseg_addr; - uintptr_t addr_offset; - - /* if secondary processes return error */ - if (rte_eal_process_type() == RTE_PROC_SECONDARY){ - RTE_LOG(ERR, EAL, "%s(): Not allowed in secondary process\n", __func__); - rte_errno = E_RTE_SECONDARY; - return NULL; - } - - /* if alignment is not a power of two */ - if (!rte_is_power_of_2(align)) { - RTE_LOG(ERR, EAL, "%s(): Invalid alignment: %u\n", __func__, - align); - rte_errno = EINVAL; - return NULL; - } - - /* alignment less than cache size is not allowed */ - if (align < CACHE_LINE_SIZE) - align = CACHE_LINE_SIZE; /* get pointer to global configuration */ - config = rte_eal_get_configuration(); + mcfg = rte_eal_get_configuration()->mem_config; /* no more room in config */ - if (memzone_idx >= RTE_MAX_MEMZONE) { + if (mcfg->memzone_idx >= RTE_MAX_MEMZONE) { RTE_LOG(ERR, EAL, "%s(): No more room in config\n", __func__); rte_errno = ENOSPC; return NULL; } - /* both sizes cannot be explicitly called for */ - if ((flags & RTE_MEMZONE_1GB) && (flags & RTE_MEMZONE_2MB)) { - rte_errno = EINVAL; - return NULL; - } - /* zone already exist */ - if (rte_memzone_lookup(name) != NULL) { + if ((memzone_lookup_thread_unsafe(name)) != NULL) { RTE_LOG(DEBUG, EAL, "%s(): memzone <%s> already exists\n", __func__, name); rte_errno = EEXIST; @@ -133,9 +122,14 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, /* align length on cache boundary */ len += CACHE_LINE_MASK; - len &= ~((uint64_t)CACHE_LINE_MASK); + len &= ~((uint64_t) CACHE_LINE_MASK); + /* save original length */ + requested_len = len; + /* reserve extra space for future alignment */ + if (len) + len += align; /* save requested length */ requested_len = len; @@ -146,7 +140,6 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, /* find the smallest segment matching requirements */ for (i = 0; i < RTE_MAX_MEMSEG; i++) { - /* last segment */ if (free_memseg[i].addr == NULL) break; @@ -201,8 +194,8 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, * try allocating again without the size parameter otherwise -fail. */ if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) && - ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB))) - return rte_memzone_reserve_aligned(name, len - align, + ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB))) + return memzone_reserve_aligned_thread_unsafe(name, len - align, socket_id, 0, align); RTE_LOG(ERR, EAL, "%s(): No appropriate segment found\n", __func__); @@ -211,13 +204,12 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, } /* get offset needed to adjust alignment */ - addr_offset = (uintptr_t) RTE_PTR_SUB( - RTE_ALIGN_CEIL(free_memseg[memseg_idx].addr, (uintptr_t) align), - (uintptr_t) free_memseg[memseg_idx].addr); + addr_offset = RTE_ALIGN_CEIL(free_memseg[memseg_idx].phys_addr, align) - + free_memseg[memseg_idx].phys_addr; /* save aligned physical and virtual addresses */ memseg_physaddr = free_memseg[memseg_idx].phys_addr + addr_offset; - memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr, addr_offset); + memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr, (uintptr_t) addr_offset); /* if we are looking for a biggest memzone */ if (requested_len == 0) @@ -233,7 +225,7 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, (char *)free_memseg[memseg_idx].addr + len; /* fill the zone in config */ - struct rte_memzone *mz = &config->mem_config->memzone[memzone_idx++]; + struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++]; rte_snprintf(mz->name, sizeof(mz->name), "%s", name); mz->phys_addr = memseg_physaddr; mz->addr = memseg_addr; @@ -245,51 +237,93 @@ rte_memzone_reserve_aligned(const char *name, uint64_t len, return mz; } +/* + * Return a pointer to a correctly filled memzone descriptor (with a + * specified alignment). If the allocation cannot be done, return NULL. + */ +const struct rte_memzone * +rte_memzone_reserve_aligned(const char *name, uint64_t len, + int socket_id, unsigned flags, unsigned align) +{ + struct rte_mem_config *mcfg; + const struct rte_memzone *mz = NULL; + + /* both sizes cannot be explicitly called for */ + if ((flags & RTE_MEMZONE_1GB) && (flags & RTE_MEMZONE_2MB)) { + rte_errno = EINVAL; + return NULL; + } + + /* if alignment is not a power of two */ + if (!rte_is_power_of_2(align)) { + RTE_LOG(ERR, EAL, "%s(): Invalid alignment: %u\n", __func__, + align); + rte_errno = EINVAL; + return NULL; + } + + /* alignment less than cache size is not allowed */ + if (align < CACHE_LINE_SIZE) + align = CACHE_LINE_SIZE; + + /* get pointer to global configuration */ + mcfg = rte_eal_get_configuration()->mem_config; + + rte_rwlock_write_lock(&mcfg->mlock); + + mz = memzone_reserve_aligned_thread_unsafe( + name, len, socket_id, flags, align); + + rte_rwlock_write_unlock(&mcfg->mlock); + + return mz; +} + /* * Lookup for the memzone identified by the given name */ const struct rte_memzone * rte_memzone_lookup(const char *name) { - const struct rte_mem_config *mcfg; - unsigned i = 0; + struct rte_mem_config *mcfg; + const struct rte_memzone *memzone = NULL; - /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; + + rte_rwlock_read_lock(&mcfg->mlock); - /* - * the algorithm is not optimal (linear), but there are few - * zones and this function should be called at init only - */ - for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) { - if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE)) - return &mcfg->memzone[i]; - } - return NULL; + memzone = memzone_lookup_thread_unsafe(name); + + rte_rwlock_read_unlock(&mcfg->mlock); + + return memzone; } /* Dump all reserved memory zones on console */ void rte_memzone_dump(void) { - const struct rte_mem_config *mcfg; + struct rte_mem_config *mcfg; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; + rte_rwlock_read_lock(&mcfg->mlock); /* dump all zones */ for (i=0; imemzone[i].addr == NULL) break; - printf("name:<%s>, phys:0x%"PRIx64", len:0x%"PRIx64"" - ", virt:%p, socket_id:%"PRId32"\n", + printf("Zone %o: name:<%s>, phys:0x%"PRIx64", len:0x%"PRIx64"" + ", virt:%p, socket_id:%"PRId32", flags:%"PRIx32"\n", i, mcfg->memzone[i].name, mcfg->memzone[i].phys_addr, mcfg->memzone[i].len, mcfg->memzone[i].addr, - mcfg->memzone[i].socket_id); + mcfg->memzone[i].socket_id, + mcfg->memzone[i].flags); } + rte_rwlock_read_unlock(&mcfg->mlock); } /* @@ -337,25 +371,30 @@ memseg_sanitize(struct rte_memseg *memseg) int rte_eal_memzone_init(void) { - struct rte_config *config; + struct rte_mem_config *mcfg; const struct rte_memseg *memseg; unsigned i = 0; + /* get pointer to global configuration */ + mcfg = rte_eal_get_configuration()->mem_config; + + /* mirror the runtime memsegs from config */ + free_memseg = mcfg->free_memseg; + /* secondary processes don't need to initialise anything */ if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; - /* get pointer to global configuration */ - config = rte_eal_get_configuration(); - memseg = rte_eal_get_physmem_layout(); if (memseg == NULL) { RTE_LOG(ERR, EAL, "%s(): Cannot get physical layout\n", __func__); return -1; } + rte_rwlock_write_lock(&mcfg->mlock); + /* duplicate the memsegs from config */ - memcpy(free_memseg, memseg, sizeof(free_memseg)); + memcpy(free_memseg, memseg, sizeof(struct rte_memseg) * RTE_MAX_MEMSEG); /* make all zones cache-aligned */ for (i=0; imlock); return -1; } } /* delete all zones */ - memzone_idx = 0; - memset(config->mem_config->memzone, 0, sizeof(config->mem_config->memzone)); + mcfg->memzone_idx = 0; + memset(mcfg->memzone, 0, sizeof(mcfg->memzone)); + + rte_rwlock_write_unlock(&mcfg->mlock); return 0; } diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c index 59c583e330..50b7379ad7 100644 --- a/lib/librte_eal/common/eal_common_tailqs.c +++ b/lib/librte_eal/common/eal_common_tailqs.c @@ -116,6 +116,7 @@ rte_dump_tailq(void) mcfg = rte_eal_get_configuration()->mem_config; + rte_rwlock_read_lock(&mcfg->qlock); for (i=0; i < RTE_MAX_TAILQ; i++) { const struct rte_tailq_head *tailq = &mcfg->tailq_head[i]; const struct rte_dummy_head *head = &tailq->tailq_head; @@ -124,6 +125,7 @@ rte_dump_tailq(void) (rte_tailq_names[i] != NULL ? rte_tailq_names[i]:"nil"), head->tqh_first, head->tqh_last); } + rte_rwlock_read_unlock(&mcfg->qlock); } int diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h index 9c85234d73..4ad87f1bc5 100644 --- a/lib/librte_eal/common/include/rte_eal.h +++ b/lib/librte_eal/common/include/rte_eal.h @@ -148,7 +148,18 @@ enum rte_proc_type_t rte_eal_process_type(void); int rte_eal_init(int argc, char **argv); /** - * Utility macro to do a tailq 'INSERT' of rte_mem_config + * macro to get the lock of tailq in mem_config + */ +#define RTE_EAL_TAILQ_RWLOCK (&rte_eal_get_configuration()->mem_config->qlock) + +/** + * macro to get the multiple lock of mempool shared by mutiple-instance + */ +#define RTE_EAL_MEMPOOL_RWLOCK (&rte_eal_get_configuration()->mem_config->mplock) + + +/** + * Utility macro to do a thread-safe tailq 'INSERT' of rte_mem_config * * @param idx * a kind of tailq define in enum rte_tailq_t @@ -163,11 +174,13 @@ int rte_eal_init(int argc, char **argv); #define RTE_EAL_TAILQ_INSERT_TAIL(idx, type, elm) do { \ struct type *list; \ list = RTE_TAILQ_LOOKUP_BY_IDX(idx, type); \ + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); \ TAILQ_INSERT_TAIL(list, elm, next); \ + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); \ } while (0) /** - * Utility macro to do a tailq 'REMOVE' of rte_mem_config + * Utility macro to do a thread-safe tailq 'REMOVE' of rte_mem_config * * @param idx * a kind of tailq define in enum rte_tailq_t @@ -182,7 +195,9 @@ int rte_eal_init(int argc, char **argv); #define RTE_EAL_TAILQ_REMOVE(idx, type, elm) do { \ struct type *list; \ list = RTE_TAILQ_LOOKUP_BY_IDX(idx, type); \ + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); \ TAILQ_REMOVE(list, elm, next); \ + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); \ } while (0) \ diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h index 6b26815704..adca8fd060 100644 --- a/lib/librte_eal/common/include/rte_eal_memconfig.h +++ b/lib/librte_eal/common/include/rte_eal_memconfig.h @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -58,18 +59,44 @@ enum rte_tailq_t { * support, the memory details should be shared across instances */ struct rte_mem_config { + volatile uint32_t magic; /**< Magic number - Sanity check. */ + /* memory topology */ uint32_t nchannel; /**< Number of channels (0 if unknown). */ uint32_t nrank; /**< Number of ranks (0 if unknown). */ + /** + * current lock nest order + * - qlock->mlock (ring/hash/lpm) + * - mplock->qlock->mlock (mempool) + * Notice: + * *ALWAYS* obtain qlock first if having to obtain both qlock and mlock + */ + rte_rwlock_t mlock; /**< only used by memzone LIB for thread-safe. */ + rte_rwlock_t qlock; /**< used for tailq operation for thread safe. */ + rte_rwlock_t mplock; /**< only used by mempool LIB for thread-safe. */ + + uint32_t memzone_idx; /**< Index of memzone */ + /* memory segments and zones */ struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */ struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */ + /* Runtime Physmem descriptors. */ + struct rte_memseg free_memseg[RTE_MAX_MEMSEG]; + struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */ } __attribute__((__packed__)); +inline static void +rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg) +{ + /* wait until shared mem_config finish initialising */ + while(mcfg->magic != RTE_MAGIC) + rte_pause(); +} + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h index 764b55b8bc..0cbcdab13b 100644 --- a/lib/librte_eal/common/include/rte_memory.h +++ b/lib/librte_eal/common/include/rte_memory.h @@ -66,9 +66,7 @@ enum rte_page_sizes { */ #define __rte_cache_aligned __attribute__((__aligned__(CACHE_LINE_SIZE))) -#ifndef __KERNEL__ /* so we can include this header in kernel modules */ typedef uint64_t phys_addr_t; /**< Physical address definition. */ -#endif /** * Physical memory segment descriptor. diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index 61dc70a93e..759f198f7c 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ #include #include #include +#include #include "eal_private.h" #include "eal_thread.h" @@ -203,14 +205,13 @@ rte_eal_config_create(void) } rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), - PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); + 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; - memcpy(rte_config.mem_config, &early_mem_config, - sizeof(early_mem_config)); } /* attach to an existing shared memory config */ @@ -224,13 +225,13 @@ rte_eal_config_attach(void) return; if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDONLY); + 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, - MAP_SHARED, mem_cfg_fd, 0); + 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) rte_panic("Cannot mmap memory for rte_config\n"); @@ -274,6 +275,7 @@ rte_config_init(void) 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: @@ -281,6 +283,25 @@ rte_config_init(void) } } +/* Unlocks hugepage directories that were locked by eal_hugepage_info_init */ +static void +eal_hugedirs_unlock(void) +{ + int i; + + for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) + { + /* skip uninitialized */ + if (internal_config.hugepage_info[i].lock_descriptor == 0) + continue; + /* unlock hugepage file */ + flock(internal_config.hugepage_info[i].lock_descriptor, LOCK_UN); + close(internal_config.hugepage_info[i].lock_descriptor); + /* reset the field */ + internal_config.hugepage_info[i].lock_descriptor = 0; + } +} + /* display usage */ static void eal_usage(const char *prgname) @@ -494,6 +515,10 @@ eal_parse_args(int argc, char **argv) for (i = 0; i < RTE_MAX_NUMA_NODES; i++) internal_config.socket_mem[i] = 0; + /* zero out hugedir descriptors */ + for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) + internal_config.hugepage_info[i].lock_descriptor = 0; + while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v", lgopts, &option_index)) != EOF) { @@ -663,12 +688,30 @@ eal_check_mem_on_local_socket(void) "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; +} + /* Launch threads, called at application init(). */ int rte_eal_init(int argc, char **argv) { int i, fctret, ret; pthread_t thread_id; + static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0); + + if (!rte_atomic32_test_and_set(&run_once)) + return -1; thread_id = pthread_self(); @@ -679,7 +722,9 @@ rte_eal_init(int argc, char **argv) if (fctret < 0) exit(1); - if (eal_hugepage_info_init() < 0) + if (internal_config.no_hugetlbfs == 0 && + internal_config.process_type != RTE_PROC_SECONDARY && + eal_hugepage_info_init() < 0) rte_panic("Cannot get hugepage information\n"); if (internal_config.memory == 0 && internal_config.force_sockets == 0) { @@ -690,14 +735,18 @@ rte_eal_init(int argc, char **argv) } rte_srand(rte_rdtsc()); - rte_config_init(); + rte_config_init(); + if (rte_eal_cpu_init() < 0) rte_panic("Cannot detect lcores\n"); if (rte_eal_memory_init() < 0) rte_panic("Cannot init memory\n"); + /* the directories are locked during eal_hugepage_info_init */ + eal_hugedirs_unlock(); + if (rte_eal_memzone_init() < 0) rte_panic("Cannot init memzone\n"); @@ -724,6 +773,8 @@ rte_eal_init(int argc, char **argv) eal_check_mem_on_local_socket(); + rte_eal_mcfg_complete(); + RTE_LCORE_FOREACH_SLAVE(i) { /* @@ -746,6 +797,13 @@ rte_eal_init(int argc, char **argv) eal_thread_init_master(rte_config.master_lcore); + /* + * Launch a dummy function on all slave lcores, so that master lcore + * knows they are all ready when this function returns. + */ + rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); + rte_eal_mp_wait_lcore(); + return fctret; } diff --git a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c index 5a0e51a7ff..c5b7881df6 100644 --- a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +++ b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c @@ -34,25 +34,28 @@ #include #include +#include #include #include #include #include +#include #include #include +#include #include #include -#include "rte_memory.h" -#include "rte_memzone.h" -#include "rte_tailq.h" -#include "rte_eal.h" -#include "rte_launch.h" -#include "rte_per_lcore.h" -#include "rte_lcore.h" -#include "rte_debug.h" -#include "rte_log.h" -#include "rte_common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "rte_string_fns.h" #include "eal_internal_cfg.h" #include "eal_hugepages.h" @@ -63,9 +66,16 @@ static const char sys_dir_path[] = "/sys/kernel/mm/hugepages"; static int32_t get_num_hugepages(const char *subdir) { - const char nr_hp_file[] = "nr_hugepages"; - char path[BUFSIZ]; - unsigned num_pages = 0; + char path[PATH_MAX]; + long unsigned num_pages = 0; + const char *nr_hp_file; + + /* if secondary process, just look at the number of hugepages, + * otherwise look at number of free hugepages */ + if (internal_config.process_type == RTE_PROC_SECONDARY) + nr_hp_file = "nr_hugepages"; + else + nr_hp_file = "free_hugepages"; rte_snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); @@ -73,7 +83,10 @@ get_num_hugepages(const char *subdir) if (eal_parse_sysfs_value(path, &num_pages) < 0) return 0; - return num_pages; + if (num_pages == 0) + RTE_LOG(ERR, EAL, "Error - no free hugepages available!\n"); + + return (int32_t)num_pages; } static uint64_t @@ -169,9 +182,79 @@ static inline void swap_hpi(struct hugepage_info *a, struct hugepage_info *b) { char buf[sizeof(*a)]; - memcpy(buf, a, sizeof(*a)); - memcpy(a, b, sizeof(*a)); - memcpy(b, buf, sizeof(*a)); + memcpy(buf, a, sizeof(buf)); + memcpy(a, b, sizeof(buf)); + memcpy(b, buf, sizeof(buf)); +} + +/* + * Clear the hugepage directory of whatever hugepage files + * there are. Checks if the file is locked (i.e. + * if it's in use by another DPDK process). + */ +static int +clear_hugedir(const char * hugedir) +{ + DIR *dir; + struct dirent *dirent; + int dir_fd, fd, lck_result; + const char filter[] = "*map_*"; /* matches hugepage files */ + + /* open directory */ + dir = opendir(hugedir); + if (!dir) { + RTE_LOG(INFO, EAL, "Unable to open hugepage directory %s\n", + hugedir); + goto error; + } + dir_fd = dirfd(dir); + + dirent = readdir(dir); + if (!dirent) { + RTE_LOG(INFO, EAL, "Unable to read hugepage directory %s\n", + hugedir); + goto error; + } + + while(dirent != NULL){ + /* skip files that don't match the hugepage pattern */ + if (fnmatch(filter, dirent->d_name, 0) > 0) { + dirent = readdir(dir); + continue; + } + + /* try and lock the file */ + fd = openat(dir_fd, dirent->d_name, O_RDONLY); + + /* skip to next file */ + if (fd == -1) { + dirent = readdir(dir); + continue; + } + + /* non-blocking lock */ + lck_result = flock(fd, LOCK_EX | LOCK_NB); + + /* if lock succeeds, unlock and remove the file */ + if (lck_result != -1) { + flock(fd, LOCK_UN); + unlinkat(dir_fd, dirent->d_name, 0); + } + close (fd); + dirent = readdir(dir); + } + + closedir(dir); + return 0; + +error: + if (dir) + closedir(dir); + + RTE_LOG(INFO, EAL, "Error while clearing hugepage dir: %s\n", + strerror(errno)); + + return -1; } /* @@ -206,6 +289,18 @@ eal_hugepage_info_init(void) (unsigned) get_num_hugepages(dirent->d_name), (unsigned long long)hpi->hugepage_sz); } else { + /* try to obtain a writelock */ + hpi->lock_descriptor = open(hpi->hugedir, O_RDONLY); + + /* if blocking lock failed */ + if (flock(hpi->lock_descriptor, LOCK_EX) == -1) { + RTE_LOG(CRIT, EAL, "Failed to lock hugepage directory!\n"); + return -1; + } + /* clear out the hugepages dir from unused pages */ + if (clear_hugedir(hpi->hugedir) == -1) + return -1; + /* for now, put all pages into socket 0, * later they will be sorted */ hpi->num_pages[0] = get_num_hugepages(dirent->d_name); diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c index 7357a128fb..ef8d36a77c 100644 --- a/lib/librte_eal/linuxapp/eal/eal_memory.c +++ b/lib/librte_eal/linuxapp/eal/eal_memory.c @@ -44,11 +44,13 @@ #include #include #include -#include +#include #include #include #include #include +#include +#include #include #include @@ -56,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +114,44 @@ aslr_enabled(void) } } +/* + * Increase limit for open files for current process + */ +static int +increase_open_file_limit(void) +{ + struct rlimit limit; + + /* read current limits */ + if (getrlimit(RLIMIT_NOFILE, &limit) != 0) { + RTE_LOG(ERR, EAL, "Error reading resource limit: %s\n", + strerror(errno)); + return -1; + } + + /* check if current soft limit matches the hard limit */ + if (limit.rlim_cur < limit.rlim_max) { + /* set soft limit to match hard limit */ + limit.rlim_cur = limit.rlim_max; + } + else { + /* we can't increase the soft limit so now we try to increase + * soft and hard limit. this might fail when run as non-root. + */ + limit.rlim_cur *= 2; + limit.rlim_max *= 2; + } + + /* set current resource limit */ + if (setrlimit(RLIMIT_NOFILE, &limit) != 0) { + RTE_LOG(ERR, EAL, "Error increasing open files limit: %s\n", + strerror(errno)); + return -1; + } + + return 0; +} + /* * Try to mmap *size bytes in /dev/zero. If it is succesful, return the * pointer to the mmap'd area and keep *size unmodified. Else, retry @@ -219,6 +260,7 @@ map_all_hugepages(struct hugepage *hugepg_tbl, vma_len = hugepage_sz; } + /* try to create hugepage file */ fd = open(hugepg_tbl[i].filepath, O_CREAT | O_RDWR, 0755); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): open failed: %s\n", __func__, @@ -243,9 +285,11 @@ map_all_hugepages(struct hugepage *hugepg_tbl, hugepg_tbl[i].final_va = virtaddr; } + /* close the file descriptor, files will be locked later */ + close(fd); + vma_addr = (char *)vma_addr + hugepage_sz; vma_len -= hugepage_sz; - close(fd); } return 0; } @@ -518,7 +562,30 @@ unmap_unneeded_hugepages(struct hugepage *hugepg_tbl, munmap(hp->final_va, hp->size); hp->final_va = NULL; } + /* lock the page and skip */ else { + /* try and open the hugepage file */ + while ((fd = open(hp->filepath, O_CREAT | O_RDWR, 0755)) < 0) { + /* if we can't open due to resource limits */ + if (errno == EMFILE) { + RTE_LOG(INFO, EAL, "Increasing open file limit\n"); + + /* if we manage to increase resource limit, try again */ + if (increase_open_file_limit() == 0) + continue; + } + else + RTE_LOG(ERR, EAL, "%s(): open failed: %s\n", __func__, + strerror(errno)); + return -1; + } + /* try and lock the hugepage */ + if (flock(fd, LOCK_SH | LOCK_NB) == -1) { + RTE_LOG(ERR, EAL, "Locking hugepage file failed!\n"); + close(fd); + return -1; + } + hp->page_lock = fd; pages_found++; } } /* match page */ diff --git a/lib/librte_eal/linuxapp/eal/include/eal_hugepages.h b/lib/librte_eal/linuxapp/eal/include/eal_hugepages.h index 73028cdf7d..b1a061b790 100644 --- a/lib/librte_eal/linuxapp/eal/include/eal_hugepages.h +++ b/lib/librte_eal/linuxapp/eal/include/eal_hugepages.h @@ -49,7 +49,8 @@ struct hugepage { int socket_id; /**< NUMA socket ID */ int file_id; /**< the '%d' in HUGEFILE_FMT */ int memseg_id; /**< the memory segment to which page belongs */ - char filepath[MAX_HUGEPAGE_PATH]; /**< Path to backing file on filesystem */ + char filepath[MAX_HUGEPAGE_PATH]; /**< path to backing file on filesystem */ + int page_lock; /**< descriptor for hugepage file */ }; /** diff --git a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h index d25a47b720..43ceca9bf2 100644 --- a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h +++ b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h @@ -53,6 +53,7 @@ struct hugepage_info { const char *hugedir; /**< dir where hugetlbfs is mounted */ uint32_t num_pages[RTE_MAX_NUMA_NODES]; /**< number of hugepages of that size on each socket */ + int lock_descriptor; /**< file descriptor for hugepage dir */ }; /** diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c index 4163c928c7..2d2b11a198 100644 --- a/lib/librte_hash/rte_fbk_hash.c +++ b/lib/librte_hash/rte_fbk_hash.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "rte_fbk_hash.h" @@ -79,10 +80,12 @@ rte_fbk_hash_find_existing(const char *name) return NULL; } + rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(h, fbk_hash_list, next) { if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0) break; } + rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (h == NULL) rte_errno = ENOENT; return h; @@ -129,19 +132,22 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params) rte_snprintf(hash_name, sizeof(hash_name), "FBK_%s", params->name); + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); + /* guarantee there's no existing */ TAILQ_FOREACH(ht, fbk_hash_list, next) { if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0) break; } if (ht != NULL) - return NULL; + goto exit; /* Allocate memory for table. */ ht = (struct rte_fbk_hash_table *)rte_malloc_socket(hash_name, mem_size, 0, params->socket_id); if (ht == NULL) - return NULL; + goto exit; + memset(ht, 0, mem_size); /* Set up hash table context. */ @@ -165,6 +171,10 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params) } TAILQ_INSERT_TAIL(fbk_hash_list, ht, next); + +exit: + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); + return ht; } diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c index e1a909aab1..007ec4425a 100644 --- a/lib/librte_hash/rte_hash.c +++ b/lib/librte_hash/rte_hash.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include "rte_hash.h" @@ -149,10 +151,13 @@ rte_hash_find_existing(const char *name) return NULL; } + rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(h, hash_list, next) { if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0) break; } + rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); + if (h == NULL) rte_errno = ENOENT; return h; @@ -205,19 +210,21 @@ rte_hash_create(const struct rte_hash_parameters *params) /* Total memory required for hash context */ mem_size = hash_tbl_size + sig_tbl_size + key_tbl_size; + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); + /* guarantee there's no existing */ TAILQ_FOREACH(h, hash_list, next) { if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0) break; } if (h != NULL) - return NULL; + goto exit; h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size, CACHE_LINE_SIZE, params->socket_id); if (h == NULL) { RTE_LOG(ERR, HASH, "memory allocation failed\n"); - return NULL; + goto exit; } /* Setup hash context */ @@ -237,6 +244,10 @@ rte_hash_create(const struct rte_hash_parameters *params) DEFAULT_HASH_FUNC : params->hash_func; TAILQ_INSERT_TAIL(hash_list, h, next); + +exit: + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); + return h; } diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c index b1bc6b301b..10705fc406 100644 --- a/lib/librte_lpm/rte_lpm.c +++ b/lib/librte_lpm/rte_lpm.c @@ -52,6 +52,8 @@ #include #include #include +#include +#include #include "rte_lpm.h" @@ -126,10 +128,12 @@ rte_lpm_find_existing(const char *name) return NULL; } + rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(l, lpm_list, next) { if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0) break; } + rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (l == NULL) rte_errno = ENOENT; @@ -179,20 +183,22 @@ rte_lpm_create(const char *name, int socket_id, int max_rules, /* Determine the amount of memory to allocate. */ mem_size = sizeof(*lpm) + (sizeof(lpm->rules_tbl[0]) * max_rules); + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); + /* guarantee there's no existing */ TAILQ_FOREACH(lpm, lpm_list, next) { if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0) break; } if (lpm != NULL) - return NULL; + goto exit; /* Allocate memory to store the LPM data structures. */ lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size, CACHE_LINE_SIZE, socket_id); if (lpm == NULL) { RTE_LOG(ERR, LPM, "LPM memory allocation failed\n"); - return NULL; + goto exit; } /* Save user arguments. */ @@ -201,6 +207,9 @@ rte_lpm_create(const char *name, int socket_id, int max_rules, TAILQ_INSERT_TAIL(lpm_list, lpm, next); +exit: + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); + return lpm; } diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c index 5db7e2e748..a54f62e10f 100644 --- a/lib/librte_mempool/rte_mempool.c +++ b/lib/librte_mempool/rte_mempool.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "rte_mempool.h" @@ -178,6 +179,8 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, if (flags & MEMPOOL_F_SC_GET) rg_flags |= RING_F_SC_DEQ; + rte_rwlock_write_lock(RTE_EAL_MEMPOOL_RWLOCK); + /* allocate the ring that will be used to store objects */ /* Ring functions will return appropriate errors if we are * running as a secondary process etc., so no checks made @@ -185,7 +188,7 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, rte_snprintf(rg_name, sizeof(rg_name), "MP_%s", name); r = rte_ring_create(rg_name, rte_align32pow2(n+1), socket_id, rg_flags); if (r == NULL) - return NULL; + goto exit; /* * In header, we have at least the pointer to the pool, and @@ -236,6 +239,7 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, mempool_size = total_elt_size * n + sizeof(struct rte_mempool) + private_data_size; rte_snprintf(mz_name, sizeof(mz_name), "MP_%s", name); + mz = rte_memzone_reserve(mz_name, mempool_size, socket_id, mz_flags); /* @@ -243,7 +247,7 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, * space for the as we cannot free it */ if (mz == NULL) - return NULL; + goto exit; /* init the mempool structure */ mp = mz->addr; @@ -289,6 +293,9 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp); +exit: + rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK); + return mp; } @@ -398,6 +405,9 @@ rte_mempool_audit(const struct rte_mempool *mp) { mempool_audit_cache(mp); mempool_audit_cookies(mp); + + /* For case where mempool DEBUG is not set, and cache size is 0 */ + RTE_SET_USED(mp); } /* dump the status of the mempool on the console */ @@ -465,9 +475,13 @@ rte_mempool_list_dump(void) return; } + rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK); + TAILQ_FOREACH(mp, mempool_list, next) { rte_mempool_dump(mp); } + + rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK); } /* search a mempool from its name */ @@ -483,10 +497,15 @@ rte_mempool_lookup(const char *name) return NULL; } + rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK); + TAILQ_FOREACH(mp, mempool_list, next) { if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0) break; } + + rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK); + if (mp == NULL) rte_errno = ENOENT; diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c index 2d6ed1f05d..6731d27c20 100644 --- a/lib/librte_ring/rte_ring.c +++ b/lib/librte_ring/rte_ring.c @@ -86,6 +86,7 @@ #include #include #include +#include #include "rte_ring.h" @@ -138,6 +139,8 @@ rte_ring_create(const char *name, unsigned count, int socket_id, rte_snprintf(mz_name, sizeof(mz_name), "RG_%s", name); ring_size = count * sizeof(void *) + sizeof(struct rte_ring); + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); + /* reserve a memory zone for this ring. If we can't get rte_config or * we are secondary process, the memzone_reserve function will set * rte_errno for us appropriately - hence no check in this this function */ @@ -162,6 +165,7 @@ rte_ring_create(const char *name, unsigned count, int socket_id, r = NULL; RTE_LOG(ERR, RING, "Cannot reserve memory\n"); } + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return r; } @@ -252,9 +256,13 @@ rte_ring_list_dump(void) return; } + rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); + TAILQ_FOREACH(mp, ring_list, next) { rte_ring_dump(mp); } + + rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); } /* search a ring from its name */ @@ -271,11 +279,15 @@ rte_ring_lookup(const char *name) return NULL; } + rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); + TAILQ_FOREACH(r, ring_list, next) { if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0) break; } + rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); + if (r == NULL) rte_errno = ENOENT;