memory: fix for multi process support
authorIntel <intel.com>
Wed, 19 Dec 2012 23:00:00 +0000 (00:00 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Thu, 25 Jul 2013 13:23:27 +0000 (15:23 +0200)
Signed-off-by: Intel
17 files changed:
app/test/test_spinlock.c
lib/librte_eal/common/eal_common_memory.c
lib/librte_eal/common/eal_common_memzone.c
lib/librte_eal/common/eal_common_tailqs.c
lib/librte_eal/common/include/rte_eal.h
lib/librte_eal/common/include/rte_eal_memconfig.h
lib/librte_eal/common/include/rte_memory.h
lib/librte_eal/linuxapp/eal/eal.c
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
lib/librte_eal/linuxapp/eal/eal_memory.c
lib/librte_eal/linuxapp/eal/include/eal_hugepages.h
lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h
lib/librte_hash/rte_fbk_hash.c
lib/librte_hash/rte_hash.c
lib/librte_lpm/rte_lpm.c
lib/librte_mempool/rte_mempool.c
lib/librte_ring/rte_ring.c

index 16036a9..841d17a 100644 (file)
@@ -35,6 +35,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/queue.h>
 
@@ -51,6 +52,7 @@
 #include <rte_lcore.h>
 #include <rte_cycles.h>
 #include <rte_spinlock.h>
+#include <rte_atomic.h>
 
 #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;
 }
index 76553f6..c150705 100644 (file)
@@ -43,6 +43,7 @@
 #include <rte_memzone.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
+#include <rte_eal_memconfig.h>
 #include <rte_log.h>
 
 #include "eal_private.h"
@@ -93,12 +94,18 @@ rte_dump_physmem_layout(void)
        for (i=0; i<RTE_MAX_MEMSEG; i++) {
                if (mcfg->memseg[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);
        }
 }
 
index df707bf..bcdd95e 100644 (file)
@@ -46,6 +46,7 @@
 #include <rte_memzone.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
+#include <rte_eal_memconfig.h>
 #include <rte_per_lcore.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #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; i<RTE_MAX_MEMZONE; i++) {
                if (mcfg->memzone[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; i<RTE_MAX_MEMSEG; i++) {
@@ -363,13 +402,16 @@ rte_eal_memzone_init(void)
                        break;
                if (memseg_sanitize(&free_memseg[i]) < 0) {
                        RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
+                       rte_rwlock_write_unlock(&mcfg->mlock);
                        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;
 }
index 59c583e..50b7379 100644 (file)
@@ -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
index 9c85234..4ad87f1 100644 (file)
@@ -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)                                                     \
 
 
index 6b26815..adca8fd 100644 (file)
@@ -38,6 +38,7 @@
 #include <rte_tailq.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_rwlock.h>
 
 #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
index 764b55b..0cbcdab 100644 (file)
@@ -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.
index 61dc70a..759f198 100644 (file)
@@ -40,7 +40,7 @@
 #include <unistd.h>
 #include <pthread.h>
 #include <getopt.h>
-#include <fcntl.h>
+#include <sys/file.h>
 #include <stddef.h>
 #include <errno.h>
 #include <limits.h>
@@ -55,6 +55,7 @@
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
+#include <rte_eal_memconfig.h>
 #include <rte_per_lcore.h>
 #include <rte_lcore.h>
 #include <rte_log.h>
@@ -66,6 +67,7 @@
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_version.h>
+#include <rte_atomic.h>
 
 #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;
 }
 
index 5a0e51a..c5b7881 100644 (file)
 
 #include <string.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include <dirent.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <fnmatch.h>
 #include <inttypes.h>
 #include <stdarg.h>
+#include <unistd.h>
 #include <errno.h>
 #include <sys/queue.h>
 
-#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 <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 "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);
index 7357a12..ef8d36a 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/queue.h>
-#include <fcntl.h>
+#include <sys/file.h>
 #include <unistd.h>
 #include <limits.h>
 #include <errno.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include <rte_log.h>
 #include <rte_memory.h>
@@ -56,6 +58,7 @@
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
+#include <rte_eal_memconfig.h>
 #include <rte_per_lcore.h>
 #include <rte_lcore.h>
 #include <rte_common.h>
@@ -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 */
index 73028cd..b1a061b 100644 (file)
@@ -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 */
 };
 
 /**
index d25a47b..43ceca9 100644 (file)
@@ -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 */
 };
 
 /**
index 4163c92..2d2b11a 100644 (file)
@@ -51,6 +51,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_log.h>
+#include <rte_spinlock.h>
 
 #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;
 }
 
index e1a909a..007ec44 100644 (file)
@@ -55,6 +55,8 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_log.h>
+#include <rte_rwlock.h>
+#include <rte_spinlock.h>
 
 #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;
 }
 
index b1bc6b3..10705fc 100644 (file)
@@ -52,6 +52,8 @@
 #include <rte_per_lcore.h>
 #include <rte_string_fns.h>
 #include <rte_errno.h>
+#include <rte_rwlock.h>
+#include <rte_spinlock.h>
 
 #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;
 }
 
index 5db7e2e..a54f62e 100644 (file)
@@ -56,6 +56,7 @@
 #include <rte_ring.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
+#include <rte_spinlock.h>
 
 #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;
 
index 2d6ed1f..6731d27 100644 (file)
@@ -86,6 +86,7 @@
 #include <rte_branch_prediction.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
+#include <rte_spinlock.h>
 
 #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;