mempool: use the list to initialize objects
[dpdk.git] / lib / librte_mempool / rte_mempool.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   Copyright(c) 2016 6WIND S.A.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdint.h>
38 #include <stdarg.h>
39 #include <unistd.h>
40 #include <inttypes.h>
41 #include <errno.h>
42 #include <sys/queue.h>
43
44 #include <rte_common.h>
45 #include <rte_log.h>
46 #include <rte_debug.h>
47 #include <rte_memory.h>
48 #include <rte_memzone.h>
49 #include <rte_malloc.h>
50 #include <rte_atomic.h>
51 #include <rte_launch.h>
52 #include <rte_eal.h>
53 #include <rte_eal_memconfig.h>
54 #include <rte_per_lcore.h>
55 #include <rte_lcore.h>
56 #include <rte_branch_prediction.h>
57 #include <rte_ring.h>
58 #include <rte_errno.h>
59 #include <rte_string_fns.h>
60 #include <rte_spinlock.h>
61
62 #include "rte_mempool.h"
63
64 TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
65
66 static struct rte_tailq_elem rte_mempool_tailq = {
67         .name = "RTE_MEMPOOL",
68 };
69 EAL_REGISTER_TAILQ(rte_mempool_tailq)
70
71 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
72 #define CALC_CACHE_FLUSHTHRESH(c)       \
73         ((typeof(c))((c) * CACHE_FLUSHTHRESH_MULTIPLIER))
74
75 /*
76  * return the greatest common divisor between a and b (fast algorithm)
77  *
78  */
79 static unsigned get_gcd(unsigned a, unsigned b)
80 {
81         unsigned c;
82
83         if (0 == a)
84                 return b;
85         if (0 == b)
86                 return a;
87
88         if (a < b) {
89                 c = a;
90                 a = b;
91                 b = c;
92         }
93
94         while (b != 0) {
95                 c = a % b;
96                 a = b;
97                 b = c;
98         }
99
100         return a;
101 }
102
103 /*
104  * Depending on memory configuration, objects addresses are spread
105  * between channels and ranks in RAM: the pool allocator will add
106  * padding between objects. This function return the new size of the
107  * object.
108  */
109 static unsigned optimize_object_size(unsigned obj_size)
110 {
111         unsigned nrank, nchan;
112         unsigned new_obj_size;
113
114         /* get number of channels */
115         nchan = rte_memory_get_nchannel();
116         if (nchan == 0)
117                 nchan = 4;
118
119         nrank = rte_memory_get_nrank();
120         if (nrank == 0)
121                 nrank = 1;
122
123         /* process new object size */
124         new_obj_size = (obj_size + RTE_MEMPOOL_ALIGN_MASK) / RTE_MEMPOOL_ALIGN;
125         while (get_gcd(new_obj_size, nrank * nchan) != 1)
126                 new_obj_size++;
127         return new_obj_size * RTE_MEMPOOL_ALIGN;
128 }
129
130 /**
131  * A mempool object iterator callback function.
132  */
133 typedef void (*rte_mempool_obj_iter_t)(void * /*obj_iter_arg*/,
134         void * /*obj_start*/,
135         void * /*obj_end*/,
136         uint32_t /*obj_index */);
137
138 static void
139 mempool_add_elem(struct rte_mempool *mp, void *obj)
140 {
141         struct rte_mempool_objhdr *hdr;
142         struct rte_mempool_objtlr *tlr __rte_unused;
143
144         obj = (char *)obj + mp->header_size;
145
146         /* set mempool ptr in header */
147         hdr = RTE_PTR_SUB(obj, sizeof(*hdr));
148         hdr->mp = mp;
149         STAILQ_INSERT_TAIL(&mp->elt_list, hdr, next);
150
151 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
152         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2;
153         tlr = __mempool_get_trailer(obj);
154         tlr->cookie = RTE_MEMPOOL_TRAILER_COOKIE;
155 #endif
156
157         /* enqueue in ring */
158         rte_ring_sp_enqueue(mp->ring, obj);
159 }
160
161 /* Iterate through objects at the given address
162  *
163  * Given the pointer to the memory, and its topology in physical memory
164  * (the physical addresses table), iterate through the "elt_num" objects
165  * of size "elt_sz" aligned at "align". For each object in this memory
166  * chunk, invoke a callback. It returns the effective number of objects
167  * in this memory.
168  */
169 static uint32_t
170 rte_mempool_obj_mem_iter(void *vaddr, uint32_t elt_num, size_t total_elt_sz,
171         size_t align, const phys_addr_t paddr[], uint32_t pg_num,
172         uint32_t pg_shift, rte_mempool_obj_iter_t obj_iter, void *obj_iter_arg)
173 {
174         uint32_t i, j, k;
175         uint32_t pgn, pgf;
176         uintptr_t end, start, va;
177         uintptr_t pg_sz;
178
179         pg_sz = (uintptr_t)1 << pg_shift;
180         va = (uintptr_t)vaddr;
181
182         i = 0;
183         j = 0;
184
185         while (i != elt_num && j != pg_num) {
186
187                 start = RTE_ALIGN_CEIL(va, align);
188                 end = start + total_elt_sz;
189
190                 /* index of the first page for the next element. */
191                 pgf = (end >> pg_shift) - (start >> pg_shift);
192
193                 /* index of the last page for the current element. */
194                 pgn = ((end - 1) >> pg_shift) - (start >> pg_shift);
195                 pgn += j;
196
197                 /* do we have enough space left for the element. */
198                 if (pgn >= pg_num)
199                         break;
200
201                 for (k = j;
202                                 k != pgn &&
203                                 paddr[k] + pg_sz == paddr[k + 1];
204                                 k++)
205                         ;
206
207                 /*
208                  * if next pgn chunks of memory physically continuous,
209                  * use it to create next element.
210                  * otherwise, just skip that chunk unused.
211                  */
212                 if (k == pgn) {
213                         if (obj_iter != NULL)
214                                 obj_iter(obj_iter_arg, (void *)start,
215                                         (void *)end, i);
216                         va = end;
217                         j += pgf;
218                         i++;
219                 } else {
220                         va = RTE_ALIGN_CEIL((va + 1), pg_sz);
221                         j++;
222                 }
223         }
224
225         return i;
226 }
227
228 /* call obj_cb() for each mempool element */
229 uint32_t
230 rte_mempool_obj_iter(struct rte_mempool *mp,
231         rte_mempool_obj_cb_t *obj_cb, void *obj_cb_arg)
232 {
233         struct rte_mempool_objhdr *hdr;
234         void *obj;
235         unsigned n = 0;
236
237         STAILQ_FOREACH(hdr, &mp->elt_list, next) {
238                 obj = (char *)hdr + sizeof(*hdr);
239                 obj_cb(mp, obj_cb_arg, obj, n);
240                 n++;
241         }
242
243         return n;
244 }
245
246 /*
247  * Populate  mempool with the objects.
248  */
249
250 static void
251 mempool_obj_populate(void *arg, void *start, void *end,
252         __rte_unused uint32_t idx)
253 {
254         struct rte_mempool *mp = arg;
255
256         mempool_add_elem(mp, start);
257         mp->elt_va_end = (uintptr_t)end;
258 }
259
260 static void
261 mempool_populate(struct rte_mempool *mp, size_t num, size_t align)
262 {
263         uint32_t elt_sz;
264
265         elt_sz = mp->elt_size + mp->header_size + mp->trailer_size;
266
267         mp->size = rte_mempool_obj_mem_iter((void *)mp->elt_va_start,
268                 num, elt_sz, align,
269                 mp->elt_pa, mp->pg_num, mp->pg_shift,
270                 mempool_obj_populate, mp);
271 }
272
273 /* get the header, trailer and total size of a mempool element. */
274 uint32_t
275 rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags,
276         struct rte_mempool_objsz *sz)
277 {
278         struct rte_mempool_objsz lsz;
279
280         sz = (sz != NULL) ? sz : &lsz;
281
282         sz->header_size = sizeof(struct rte_mempool_objhdr);
283         if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0)
284                 sz->header_size = RTE_ALIGN_CEIL(sz->header_size,
285                         RTE_MEMPOOL_ALIGN);
286
287         sz->trailer_size = sizeof(struct rte_mempool_objtlr);
288
289         /* element size is 8 bytes-aligned at least */
290         sz->elt_size = RTE_ALIGN_CEIL(elt_size, sizeof(uint64_t));
291
292         /* expand trailer to next cache line */
293         if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0) {
294                 sz->total_size = sz->header_size + sz->elt_size +
295                         sz->trailer_size;
296                 sz->trailer_size += ((RTE_MEMPOOL_ALIGN -
297                                   (sz->total_size & RTE_MEMPOOL_ALIGN_MASK)) &
298                                  RTE_MEMPOOL_ALIGN_MASK);
299         }
300
301         /*
302          * increase trailer to add padding between objects in order to
303          * spread them across memory channels/ranks
304          */
305         if ((flags & MEMPOOL_F_NO_SPREAD) == 0) {
306                 unsigned new_size;
307                 new_size = optimize_object_size(sz->header_size + sz->elt_size +
308                         sz->trailer_size);
309                 sz->trailer_size = new_size - sz->header_size - sz->elt_size;
310         }
311
312         if (! rte_eal_has_hugepages()) {
313                 /*
314                  * compute trailer size so that pool elements fit exactly in
315                  * a standard page
316                  */
317                 int page_size = getpagesize();
318                 int new_size = page_size - sz->header_size - sz->elt_size;
319                 if (new_size < 0 || (unsigned int)new_size < sz->trailer_size) {
320                         printf("When hugepages are disabled, pool objects "
321                                "can't exceed PAGE_SIZE: %d + %d + %d > %d\n",
322                                sz->header_size, sz->elt_size, sz->trailer_size,
323                                page_size);
324                         return 0;
325                 }
326                 sz->trailer_size = new_size;
327         }
328
329         /* this is the size of an object, including header and trailer */
330         sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size;
331
332         return sz->total_size;
333 }
334
335
336 /*
337  * Calculate maximum amount of memory required to store given number of objects.
338  */
339 size_t
340 rte_mempool_xmem_size(uint32_t elt_num, size_t total_elt_sz, uint32_t pg_shift)
341 {
342         size_t n, pg_num, pg_sz, sz;
343
344         pg_sz = (size_t)1 << pg_shift;
345
346         if ((n = pg_sz / total_elt_sz) > 0) {
347                 pg_num = (elt_num + n - 1) / n;
348                 sz = pg_num << pg_shift;
349         } else {
350                 sz = RTE_ALIGN_CEIL(total_elt_sz, pg_sz) * elt_num;
351         }
352
353         return sz;
354 }
355
356 /* Callback used by rte_mempool_xmem_usage(): it sets the opaque
357  * argument to the end of the object.
358  */
359 static void
360 mempool_lelem_iter(void *arg, __rte_unused void *start, void *end,
361         __rte_unused uint32_t idx)
362 {
363         *(uintptr_t *)arg = (uintptr_t)end;
364 }
365
366 /*
367  * Calculate how much memory would be actually required with the
368  * given memory footprint to store required number of elements.
369  */
370 ssize_t
371 rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, size_t total_elt_sz,
372         const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift)
373 {
374         uint32_t n;
375         uintptr_t va, uv;
376         size_t pg_sz, usz;
377
378         pg_sz = (size_t)1 << pg_shift;
379         va = (uintptr_t)vaddr;
380         uv = va;
381
382         if ((n = rte_mempool_obj_mem_iter(vaddr, elt_num, total_elt_sz, 1,
383                         paddr, pg_num, pg_shift, mempool_lelem_iter,
384                         &uv)) != elt_num) {
385                 return -(ssize_t)n;
386         }
387
388         uv = RTE_ALIGN_CEIL(uv, pg_sz);
389         usz = uv - va;
390         return usz;
391 }
392
393 #ifndef RTE_LIBRTE_XEN_DOM0
394 /* stub if DOM0 support not configured */
395 struct rte_mempool *
396 rte_dom0_mempool_create(const char *name __rte_unused,
397                         unsigned n __rte_unused,
398                         unsigned elt_size __rte_unused,
399                         unsigned cache_size __rte_unused,
400                         unsigned private_data_size __rte_unused,
401                         rte_mempool_ctor_t *mp_init __rte_unused,
402                         void *mp_init_arg __rte_unused,
403                         rte_mempool_obj_ctor_t *obj_init __rte_unused,
404                         void *obj_init_arg __rte_unused,
405                         int socket_id __rte_unused,
406                         unsigned flags __rte_unused)
407 {
408         rte_errno = EINVAL;
409         return NULL;
410 }
411 #endif
412
413 /* create the mempool */
414 struct rte_mempool *
415 rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
416                    unsigned cache_size, unsigned private_data_size,
417                    rte_mempool_ctor_t *mp_init, void *mp_init_arg,
418                    rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg,
419                    int socket_id, unsigned flags)
420 {
421         if (rte_xen_dom0_supported())
422                 return rte_dom0_mempool_create(name, n, elt_size,
423                                                cache_size, private_data_size,
424                                                mp_init, mp_init_arg,
425                                                obj_init, obj_init_arg,
426                                                socket_id, flags);
427         else
428                 return rte_mempool_xmem_create(name, n, elt_size,
429                                                cache_size, private_data_size,
430                                                mp_init, mp_init_arg,
431                                                obj_init, obj_init_arg,
432                                                socket_id, flags,
433                                                NULL, NULL, MEMPOOL_PG_NUM_DEFAULT,
434                                                MEMPOOL_PG_SHIFT_MAX);
435 }
436
437 /*
438  * Create the mempool over already allocated chunk of memory.
439  * That external memory buffer can consists of physically disjoint pages.
440  * Setting vaddr to NULL, makes mempool to fallback to original behaviour
441  * and allocate space for mempool and it's elements as one big chunk of
442  * physically continuos memory.
443  * */
444 struct rte_mempool *
445 rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
446                 unsigned cache_size, unsigned private_data_size,
447                 rte_mempool_ctor_t *mp_init, void *mp_init_arg,
448                 rte_mempool_obj_cb_t *obj_init, void *obj_init_arg,
449                 int socket_id, unsigned flags, void *vaddr,
450                 const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift)
451 {
452         char mz_name[RTE_MEMZONE_NAMESIZE];
453         char rg_name[RTE_RING_NAMESIZE];
454         struct rte_mempool_list *mempool_list;
455         struct rte_mempool *mp = NULL;
456         struct rte_tailq_entry *te = NULL;
457         struct rte_ring *r = NULL;
458         const struct rte_memzone *mz;
459         size_t mempool_size;
460         int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY;
461         int rg_flags = 0;
462         void *obj;
463         struct rte_mempool_objsz objsz;
464         void *startaddr;
465         int page_size = getpagesize();
466
467         /* compilation-time checks */
468         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool) &
469                           RTE_CACHE_LINE_MASK) != 0);
470         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_cache) &
471                           RTE_CACHE_LINE_MASK) != 0);
472 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
473         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_debug_stats) &
474                           RTE_CACHE_LINE_MASK) != 0);
475         RTE_BUILD_BUG_ON((offsetof(struct rte_mempool, stats) &
476                           RTE_CACHE_LINE_MASK) != 0);
477 #endif
478
479         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
480
481         /* asked cache too big */
482         if (cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE ||
483             CALC_CACHE_FLUSHTHRESH(cache_size) > n) {
484                 rte_errno = EINVAL;
485                 return NULL;
486         }
487
488         /* check that we have both VA and PA */
489         if (vaddr != NULL && paddr == NULL) {
490                 rte_errno = EINVAL;
491                 return NULL;
492         }
493
494         /* Check that pg_num and pg_shift parameters are valid. */
495         if (pg_num < RTE_DIM(mp->elt_pa) || pg_shift > MEMPOOL_PG_SHIFT_MAX) {
496                 rte_errno = EINVAL;
497                 return NULL;
498         }
499
500         /* "no cache align" imply "no spread" */
501         if (flags & MEMPOOL_F_NO_CACHE_ALIGN)
502                 flags |= MEMPOOL_F_NO_SPREAD;
503
504         /* ring flags */
505         if (flags & MEMPOOL_F_SP_PUT)
506                 rg_flags |= RING_F_SP_ENQ;
507         if (flags & MEMPOOL_F_SC_GET)
508                 rg_flags |= RING_F_SC_DEQ;
509
510         /* calculate mempool object sizes. */
511         if (!rte_mempool_calc_obj_size(elt_size, flags, &objsz)) {
512                 rte_errno = EINVAL;
513                 return NULL;
514         }
515
516         rte_rwlock_write_lock(RTE_EAL_MEMPOOL_RWLOCK);
517
518         /* allocate the ring that will be used to store objects */
519         /* Ring functions will return appropriate errors if we are
520          * running as a secondary process etc., so no checks made
521          * in this function for that condition */
522         snprintf(rg_name, sizeof(rg_name), RTE_MEMPOOL_MZ_FORMAT, name);
523         r = rte_ring_create(rg_name, rte_align32pow2(n+1), socket_id, rg_flags);
524         if (r == NULL)
525                 goto exit_unlock;
526
527         /*
528          * reserve a memory zone for this mempool: private data is
529          * cache-aligned
530          */
531         private_data_size = (private_data_size +
532                              RTE_MEMPOOL_ALIGN_MASK) & (~RTE_MEMPOOL_ALIGN_MASK);
533
534         if (! rte_eal_has_hugepages()) {
535                 /*
536                  * expand private data size to a whole page, so that the
537                  * first pool element will start on a new standard page
538                  */
539                 int head = sizeof(struct rte_mempool);
540                 int new_size = (private_data_size + head) % page_size;
541                 if (new_size)
542                         private_data_size += page_size - new_size;
543         }
544
545         /* try to allocate tailq entry */
546         te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
547         if (te == NULL) {
548                 RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
549                 goto exit_unlock;
550         }
551
552         /*
553          * If user provided an external memory buffer, then use it to
554          * store mempool objects. Otherwise reserve a memzone that is large
555          * enough to hold mempool header and metadata plus mempool objects.
556          */
557         mempool_size = MEMPOOL_HEADER_SIZE(mp, pg_num, cache_size);
558         mempool_size += private_data_size;
559         mempool_size = RTE_ALIGN_CEIL(mempool_size, RTE_MEMPOOL_ALIGN);
560         if (vaddr == NULL)
561                 mempool_size += (size_t)objsz.total_size * n;
562
563         if (! rte_eal_has_hugepages()) {
564                 /*
565                  * we want the memory pool to start on a page boundary,
566                  * because pool elements crossing page boundaries would
567                  * result in discontiguous physical addresses
568                  */
569                 mempool_size += page_size;
570         }
571
572         snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_MZ_FORMAT, name);
573
574         mz = rte_memzone_reserve(mz_name, mempool_size, socket_id, mz_flags);
575         if (mz == NULL)
576                 goto exit_unlock;
577
578         if (rte_eal_has_hugepages()) {
579                 startaddr = (void*)mz->addr;
580         } else {
581                 /* align memory pool start address on a page boundary */
582                 unsigned long addr = (unsigned long)mz->addr;
583                 if (addr & (page_size - 1)) {
584                         addr += page_size;
585                         addr &= ~(page_size - 1);
586                 }
587                 startaddr = (void*)addr;
588         }
589
590         /* init the mempool structure */
591         mp = startaddr;
592         memset(mp, 0, sizeof(*mp));
593         snprintf(mp->name, sizeof(mp->name), "%s", name);
594         mp->phys_addr = mz->phys_addr;
595         mp->ring = r;
596         mp->size = n;
597         mp->flags = flags;
598         mp->elt_size = objsz.elt_size;
599         mp->header_size = objsz.header_size;
600         mp->trailer_size = objsz.trailer_size;
601         mp->cache_size = cache_size;
602         mp->cache_flushthresh = CALC_CACHE_FLUSHTHRESH(cache_size);
603         mp->private_data_size = private_data_size;
604         STAILQ_INIT(&mp->elt_list);
605
606         /*
607          * local_cache pointer is set even if cache_size is zero.
608          * The local_cache points to just past the elt_pa[] array.
609          */
610         mp->local_cache = (struct rte_mempool_cache *)
611                 RTE_PTR_ADD(mp, MEMPOOL_HEADER_SIZE(mp, pg_num, 0));
612
613         /* calculate address of the first element for continuous mempool. */
614         obj = (char *)mp + MEMPOOL_HEADER_SIZE(mp, pg_num, cache_size) +
615                 private_data_size;
616         obj = RTE_PTR_ALIGN_CEIL(obj, RTE_MEMPOOL_ALIGN);
617
618         /* populate address translation fields. */
619         mp->pg_num = pg_num;
620         mp->pg_shift = pg_shift;
621         mp->pg_mask = RTE_LEN2MASK(mp->pg_shift, typeof(mp->pg_mask));
622
623         /* mempool elements allocated together with mempool */
624         if (vaddr == NULL) {
625                 mp->elt_va_start = (uintptr_t)obj;
626                 mp->elt_pa[0] = mp->phys_addr +
627                         (mp->elt_va_start - (uintptr_t)mp);
628         } else {
629                 /* mempool elements in a separate chunk of memory. */
630                 mp->elt_va_start = (uintptr_t)vaddr;
631                 memcpy(mp->elt_pa, paddr, sizeof (mp->elt_pa[0]) * pg_num);
632         }
633
634         mp->elt_va_end = mp->elt_va_start;
635
636         /* call the initializer */
637         if (mp_init)
638                 mp_init(mp, mp_init_arg);
639
640         mempool_populate(mp, n, 1);
641
642         /* call the initializer */
643         if (obj_init)
644                 rte_mempool_obj_iter(mp, obj_init, obj_init_arg);
645
646         te->data = (void *) mp;
647
648         rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
649         TAILQ_INSERT_TAIL(mempool_list, te, next);
650         rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
651         rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
652
653         return mp;
654
655 exit_unlock:
656         rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
657         rte_ring_free(r);
658         rte_free(te);
659
660         return NULL;
661 }
662
663 /* Return the number of entries in the mempool */
664 unsigned
665 rte_mempool_count(const struct rte_mempool *mp)
666 {
667         unsigned count;
668         unsigned lcore_id;
669
670         count = rte_ring_count(mp->ring);
671
672         if (mp->cache_size == 0)
673                 return count;
674
675         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++)
676                 count += mp->local_cache[lcore_id].len;
677
678         /*
679          * due to race condition (access to len is not locked), the
680          * total can be greater than size... so fix the result
681          */
682         if (count > mp->size)
683                 return mp->size;
684         return count;
685 }
686
687 /* dump the cache status */
688 static unsigned
689 rte_mempool_dump_cache(FILE *f, const struct rte_mempool *mp)
690 {
691         unsigned lcore_id;
692         unsigned count = 0;
693         unsigned cache_count;
694
695         fprintf(f, "  cache infos:\n");
696         fprintf(f, "    cache_size=%"PRIu32"\n", mp->cache_size);
697
698         if (mp->cache_size == 0)
699                 return count;
700
701         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
702                 cache_count = mp->local_cache[lcore_id].len;
703                 fprintf(f, "    cache_count[%u]=%u\n", lcore_id, cache_count);
704                 count += cache_count;
705         }
706         fprintf(f, "    total_cache_count=%u\n", count);
707         return count;
708 }
709
710 #ifndef __INTEL_COMPILER
711 #pragma GCC diagnostic ignored "-Wcast-qual"
712 #endif
713
714 /* check and update cookies or panic (internal) */
715 void rte_mempool_check_cookies(const struct rte_mempool *mp,
716         void * const *obj_table_const, unsigned n, int free)
717 {
718 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
719         struct rte_mempool_objhdr *hdr;
720         struct rte_mempool_objtlr *tlr;
721         uint64_t cookie;
722         void *tmp;
723         void *obj;
724         void **obj_table;
725
726         /* Force to drop the "const" attribute. This is done only when
727          * DEBUG is enabled */
728         tmp = (void *) obj_table_const;
729         obj_table = (void **) tmp;
730
731         while (n--) {
732                 obj = obj_table[n];
733
734                 if (rte_mempool_from_obj(obj) != mp)
735                         rte_panic("MEMPOOL: object is owned by another "
736                                   "mempool\n");
737
738                 hdr = __mempool_get_header(obj);
739                 cookie = hdr->cookie;
740
741                 if (free == 0) {
742                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE1) {
743                                 rte_log_set_history(0);
744                                 RTE_LOG(CRIT, MEMPOOL,
745                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
746                                         obj, (const void *) mp, cookie);
747                                 rte_panic("MEMPOOL: bad header cookie (put)\n");
748                         }
749                         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2;
750                 } else if (free == 1) {
751                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE2) {
752                                 rte_log_set_history(0);
753                                 RTE_LOG(CRIT, MEMPOOL,
754                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
755                                         obj, (const void *) mp, cookie);
756                                 rte_panic("MEMPOOL: bad header cookie (get)\n");
757                         }
758                         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE1;
759                 } else if (free == 2) {
760                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE1 &&
761                             cookie != RTE_MEMPOOL_HEADER_COOKIE2) {
762                                 rte_log_set_history(0);
763                                 RTE_LOG(CRIT, MEMPOOL,
764                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
765                                         obj, (const void *) mp, cookie);
766                                 rte_panic("MEMPOOL: bad header cookie (audit)\n");
767                         }
768                 }
769                 tlr = __mempool_get_trailer(obj);
770                 cookie = tlr->cookie;
771                 if (cookie != RTE_MEMPOOL_TRAILER_COOKIE) {
772                         rte_log_set_history(0);
773                         RTE_LOG(CRIT, MEMPOOL,
774                                 "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
775                                 obj, (const void *) mp, cookie);
776                         rte_panic("MEMPOOL: bad trailer cookie\n");
777                 }
778         }
779 #else
780         RTE_SET_USED(mp);
781         RTE_SET_USED(obj_table_const);
782         RTE_SET_USED(n);
783         RTE_SET_USED(free);
784 #endif
785 }
786
787 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
788 static void
789 mempool_obj_audit(struct rte_mempool *mp, __rte_unused void *opaque,
790         void *obj, __rte_unused unsigned idx)
791 {
792         __mempool_check_cookies(mp, &obj, 1, 2);
793 }
794
795 static void
796 mempool_audit_cookies(struct rte_mempool *mp)
797 {
798         unsigned num;
799
800         num = rte_mempool_obj_iter(mp, mempool_obj_audit, NULL);
801         if (num != mp->size) {
802                 rte_panic("rte_mempool_obj_iter(mempool=%p, size=%u) "
803                         "iterated only over %u elements\n",
804                         mp, mp->size, num);
805         }
806 }
807 #else
808 #define mempool_audit_cookies(mp) do {} while(0)
809 #endif
810
811 #ifndef __INTEL_COMPILER
812 #pragma GCC diagnostic error "-Wcast-qual"
813 #endif
814
815 /* check cookies before and after objects */
816 static void
817 mempool_audit_cache(const struct rte_mempool *mp)
818 {
819         /* check cache size consistency */
820         unsigned lcore_id;
821
822         if (mp->cache_size == 0)
823                 return;
824
825         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
826                 if (mp->local_cache[lcore_id].len > mp->cache_flushthresh) {
827                         RTE_LOG(CRIT, MEMPOOL, "badness on cache[%u]\n",
828                                 lcore_id);
829                         rte_panic("MEMPOOL: invalid cache len\n");
830                 }
831         }
832 }
833
834 /* check the consistency of mempool (size, cookies, ...) */
835 void
836 rte_mempool_audit(struct rte_mempool *mp)
837 {
838         mempool_audit_cache(mp);
839         mempool_audit_cookies(mp);
840
841         /* For case where mempool DEBUG is not set, and cache size is 0 */
842         RTE_SET_USED(mp);
843 }
844
845 /* dump the status of the mempool on the console */
846 void
847 rte_mempool_dump(FILE *f, struct rte_mempool *mp)
848 {
849 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
850         struct rte_mempool_debug_stats sum;
851         unsigned lcore_id;
852 #endif
853         unsigned common_count;
854         unsigned cache_count;
855
856         RTE_ASSERT(f != NULL);
857         RTE_ASSERT(mp != NULL);
858
859         fprintf(f, "mempool <%s>@%p\n", mp->name, mp);
860         fprintf(f, "  flags=%x\n", mp->flags);
861         fprintf(f, "  ring=<%s>@%p\n", mp->ring->name, mp->ring);
862         fprintf(f, "  phys_addr=0x%" PRIx64 "\n", mp->phys_addr);
863         fprintf(f, "  size=%"PRIu32"\n", mp->size);
864         fprintf(f, "  header_size=%"PRIu32"\n", mp->header_size);
865         fprintf(f, "  elt_size=%"PRIu32"\n", mp->elt_size);
866         fprintf(f, "  trailer_size=%"PRIu32"\n", mp->trailer_size);
867         fprintf(f, "  total_obj_size=%"PRIu32"\n",
868                mp->header_size + mp->elt_size + mp->trailer_size);
869
870         fprintf(f, "  private_data_size=%"PRIu32"\n", mp->private_data_size);
871         fprintf(f, "  pg_num=%"PRIu32"\n", mp->pg_num);
872         fprintf(f, "  pg_shift=%"PRIu32"\n", mp->pg_shift);
873         fprintf(f, "  pg_mask=%#tx\n", mp->pg_mask);
874         fprintf(f, "  elt_va_start=%#tx\n", mp->elt_va_start);
875         fprintf(f, "  elt_va_end=%#tx\n", mp->elt_va_end);
876         fprintf(f, "  elt_pa[0]=0x%" PRIx64 "\n", mp->elt_pa[0]);
877
878         if (mp->size != 0)
879                 fprintf(f, "  avg bytes/object=%#Lf\n",
880                         (long double)(mp->elt_va_end - mp->elt_va_start) /
881                         mp->size);
882
883         cache_count = rte_mempool_dump_cache(f, mp);
884         common_count = rte_ring_count(mp->ring);
885         if ((cache_count + common_count) > mp->size)
886                 common_count = mp->size - cache_count;
887         fprintf(f, "  common_pool_count=%u\n", common_count);
888
889         /* sum and dump statistics */
890 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
891         memset(&sum, 0, sizeof(sum));
892         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
893                 sum.put_bulk += mp->stats[lcore_id].put_bulk;
894                 sum.put_objs += mp->stats[lcore_id].put_objs;
895                 sum.get_success_bulk += mp->stats[lcore_id].get_success_bulk;
896                 sum.get_success_objs += mp->stats[lcore_id].get_success_objs;
897                 sum.get_fail_bulk += mp->stats[lcore_id].get_fail_bulk;
898                 sum.get_fail_objs += mp->stats[lcore_id].get_fail_objs;
899         }
900         fprintf(f, "  stats:\n");
901         fprintf(f, "    put_bulk=%"PRIu64"\n", sum.put_bulk);
902         fprintf(f, "    put_objs=%"PRIu64"\n", sum.put_objs);
903         fprintf(f, "    get_success_bulk=%"PRIu64"\n", sum.get_success_bulk);
904         fprintf(f, "    get_success_objs=%"PRIu64"\n", sum.get_success_objs);
905         fprintf(f, "    get_fail_bulk=%"PRIu64"\n", sum.get_fail_bulk);
906         fprintf(f, "    get_fail_objs=%"PRIu64"\n", sum.get_fail_objs);
907 #else
908         fprintf(f, "  no statistics available\n");
909 #endif
910
911         rte_mempool_audit(mp);
912 }
913
914 /* dump the status of all mempools on the console */
915 void
916 rte_mempool_list_dump(FILE *f)
917 {
918         struct rte_mempool *mp = NULL;
919         struct rte_tailq_entry *te;
920         struct rte_mempool_list *mempool_list;
921
922         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
923
924         rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
925
926         TAILQ_FOREACH(te, mempool_list, next) {
927                 mp = (struct rte_mempool *) te->data;
928                 rte_mempool_dump(f, mp);
929         }
930
931         rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
932 }
933
934 /* search a mempool from its name */
935 struct rte_mempool *
936 rte_mempool_lookup(const char *name)
937 {
938         struct rte_mempool *mp = NULL;
939         struct rte_tailq_entry *te;
940         struct rte_mempool_list *mempool_list;
941
942         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
943
944         rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
945
946         TAILQ_FOREACH(te, mempool_list, next) {
947                 mp = (struct rte_mempool *) te->data;
948                 if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
949                         break;
950         }
951
952         rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
953
954         if (te == NULL) {
955                 rte_errno = ENOENT;
956                 return NULL;
957         }
958
959         return mp;
960 }
961
962 void rte_mempool_walk(void (*func)(struct rte_mempool *, void *),
963                       void *arg)
964 {
965         struct rte_tailq_entry *te = NULL;
966         struct rte_mempool_list *mempool_list;
967
968         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
969
970         rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
971
972         TAILQ_FOREACH(te, mempool_list, next) {
973                 (*func)((struct rte_mempool *) te->data, arg);
974         }
975
976         rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
977 }