mempool: add event callbacks
[dpdk.git] / lib / mempool / rte_mempool.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright(c) 2016 6WIND S.A.
4  */
5
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdint.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12 #include <inttypes.h>
13 #include <errno.h>
14 #include <sys/queue.h>
15
16 #include <rte_common.h>
17 #include <rte_log.h>
18 #include <rte_debug.h>
19 #include <rte_memory.h>
20 #include <rte_memzone.h>
21 #include <rte_malloc.h>
22 #include <rte_atomic.h>
23 #include <rte_launch.h>
24 #include <rte_eal.h>
25 #include <rte_eal_memconfig.h>
26 #include <rte_per_lcore.h>
27 #include <rte_lcore.h>
28 #include <rte_branch_prediction.h>
29 #include <rte_errno.h>
30 #include <rte_string_fns.h>
31 #include <rte_spinlock.h>
32 #include <rte_tailq.h>
33 #include <rte_eal_paging.h>
34
35 #include "rte_mempool.h"
36 #include "rte_mempool_trace.h"
37
38 TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
39
40 static struct rte_tailq_elem rte_mempool_tailq = {
41         .name = "RTE_MEMPOOL",
42 };
43 EAL_REGISTER_TAILQ(rte_mempool_tailq)
44
45 TAILQ_HEAD(mempool_callback_list, rte_tailq_entry);
46
47 static struct rte_tailq_elem callback_tailq = {
48         .name = "RTE_MEMPOOL_CALLBACK",
49 };
50 EAL_REGISTER_TAILQ(callback_tailq)
51
52 /* Invoke all registered mempool event callbacks. */
53 static void
54 mempool_event_callback_invoke(enum rte_mempool_event event,
55                               struct rte_mempool *mp);
56
57 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
58 #define CALC_CACHE_FLUSHTHRESH(c)       \
59         ((typeof(c))((c) * CACHE_FLUSHTHRESH_MULTIPLIER))
60
61 #if defined(RTE_ARCH_X86)
62 /*
63  * return the greatest common divisor between a and b (fast algorithm)
64  *
65  */
66 static unsigned get_gcd(unsigned a, unsigned b)
67 {
68         unsigned c;
69
70         if (0 == a)
71                 return b;
72         if (0 == b)
73                 return a;
74
75         if (a < b) {
76                 c = a;
77                 a = b;
78                 b = c;
79         }
80
81         while (b != 0) {
82                 c = a % b;
83                 a = b;
84                 b = c;
85         }
86
87         return a;
88 }
89
90 /*
91  * Depending on memory configuration on x86 arch, objects addresses are spread
92  * between channels and ranks in RAM: the pool allocator will add
93  * padding between objects. This function return the new size of the
94  * object.
95  */
96 static unsigned int
97 arch_mem_object_align(unsigned int obj_size)
98 {
99         unsigned nrank, nchan;
100         unsigned new_obj_size;
101
102         /* get number of channels */
103         nchan = rte_memory_get_nchannel();
104         if (nchan == 0)
105                 nchan = 4;
106
107         nrank = rte_memory_get_nrank();
108         if (nrank == 0)
109                 nrank = 1;
110
111         /* process new object size */
112         new_obj_size = (obj_size + RTE_MEMPOOL_ALIGN_MASK) / RTE_MEMPOOL_ALIGN;
113         while (get_gcd(new_obj_size, nrank * nchan) != 1)
114                 new_obj_size++;
115         return new_obj_size * RTE_MEMPOOL_ALIGN;
116 }
117 #else
118 static unsigned int
119 arch_mem_object_align(unsigned int obj_size)
120 {
121         return obj_size;
122 }
123 #endif
124
125 struct pagesz_walk_arg {
126         int socket_id;
127         size_t min;
128 };
129
130 static int
131 find_min_pagesz(const struct rte_memseg_list *msl, void *arg)
132 {
133         struct pagesz_walk_arg *wa = arg;
134         bool valid;
135
136         /*
137          * we need to only look at page sizes available for a particular socket
138          * ID.  so, we either need an exact match on socket ID (can match both
139          * native and external memory), or, if SOCKET_ID_ANY was specified as a
140          * socket ID argument, we must only look at native memory and ignore any
141          * page sizes associated with external memory.
142          */
143         valid = msl->socket_id == wa->socket_id;
144         valid |= wa->socket_id == SOCKET_ID_ANY && msl->external == 0;
145
146         if (valid && msl->page_sz < wa->min)
147                 wa->min = msl->page_sz;
148
149         return 0;
150 }
151
152 static size_t
153 get_min_page_size(int socket_id)
154 {
155         struct pagesz_walk_arg wa;
156
157         wa.min = SIZE_MAX;
158         wa.socket_id = socket_id;
159
160         rte_memseg_list_walk(find_min_pagesz, &wa);
161
162         return wa.min == SIZE_MAX ? (size_t) rte_mem_page_size() : wa.min;
163 }
164
165
166 static void
167 mempool_add_elem(struct rte_mempool *mp, __rte_unused void *opaque,
168                  void *obj, rte_iova_t iova)
169 {
170         struct rte_mempool_objhdr *hdr;
171         struct rte_mempool_objtlr *tlr __rte_unused;
172
173         /* set mempool ptr in header */
174         hdr = RTE_PTR_SUB(obj, sizeof(*hdr));
175         hdr->mp = mp;
176         hdr->iova = iova;
177         STAILQ_INSERT_TAIL(&mp->elt_list, hdr, next);
178         mp->populated_size++;
179
180 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
181         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2;
182         tlr = __mempool_get_trailer(obj);
183         tlr->cookie = RTE_MEMPOOL_TRAILER_COOKIE;
184 #endif
185 }
186
187 /* call obj_cb() for each mempool element */
188 uint32_t
189 rte_mempool_obj_iter(struct rte_mempool *mp,
190         rte_mempool_obj_cb_t *obj_cb, void *obj_cb_arg)
191 {
192         struct rte_mempool_objhdr *hdr;
193         void *obj;
194         unsigned n = 0;
195
196         STAILQ_FOREACH(hdr, &mp->elt_list, next) {
197                 obj = (char *)hdr + sizeof(*hdr);
198                 obj_cb(mp, obj_cb_arg, obj, n);
199                 n++;
200         }
201
202         return n;
203 }
204
205 /* call mem_cb() for each mempool memory chunk */
206 uint32_t
207 rte_mempool_mem_iter(struct rte_mempool *mp,
208         rte_mempool_mem_cb_t *mem_cb, void *mem_cb_arg)
209 {
210         struct rte_mempool_memhdr *hdr;
211         unsigned n = 0;
212
213         STAILQ_FOREACH(hdr, &mp->mem_list, next) {
214                 mem_cb(mp, mem_cb_arg, hdr, n);
215                 n++;
216         }
217
218         return n;
219 }
220
221 /* get the header, trailer and total size of a mempool element. */
222 uint32_t
223 rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags,
224         struct rte_mempool_objsz *sz)
225 {
226         struct rte_mempool_objsz lsz;
227
228         sz = (sz != NULL) ? sz : &lsz;
229
230         sz->header_size = sizeof(struct rte_mempool_objhdr);
231         if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0)
232                 sz->header_size = RTE_ALIGN_CEIL(sz->header_size,
233                         RTE_MEMPOOL_ALIGN);
234
235 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
236         sz->trailer_size = sizeof(struct rte_mempool_objtlr);
237 #else
238         sz->trailer_size = 0;
239 #endif
240
241         /* element size is 8 bytes-aligned at least */
242         sz->elt_size = RTE_ALIGN_CEIL(elt_size, sizeof(uint64_t));
243
244         /* expand trailer to next cache line */
245         if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0) {
246                 sz->total_size = sz->header_size + sz->elt_size +
247                         sz->trailer_size;
248                 sz->trailer_size += ((RTE_MEMPOOL_ALIGN -
249                                   (sz->total_size & RTE_MEMPOOL_ALIGN_MASK)) &
250                                  RTE_MEMPOOL_ALIGN_MASK);
251         }
252
253         /*
254          * increase trailer to add padding between objects in order to
255          * spread them across memory channels/ranks
256          */
257         if ((flags & MEMPOOL_F_NO_SPREAD) == 0) {
258                 unsigned new_size;
259                 new_size = arch_mem_object_align
260                             (sz->header_size + sz->elt_size + sz->trailer_size);
261                 sz->trailer_size = new_size - sz->header_size - sz->elt_size;
262         }
263
264         /* this is the size of an object, including header and trailer */
265         sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size;
266
267         return sz->total_size;
268 }
269
270 /* free a memchunk allocated with rte_memzone_reserve() */
271 static void
272 rte_mempool_memchunk_mz_free(__rte_unused struct rte_mempool_memhdr *memhdr,
273         void *opaque)
274 {
275         const struct rte_memzone *mz = opaque;
276         rte_memzone_free(mz);
277 }
278
279 /* Free memory chunks used by a mempool. Objects must be in pool */
280 static void
281 rte_mempool_free_memchunks(struct rte_mempool *mp)
282 {
283         struct rte_mempool_memhdr *memhdr;
284         void *elt;
285
286         while (!STAILQ_EMPTY(&mp->elt_list)) {
287                 rte_mempool_ops_dequeue_bulk(mp, &elt, 1);
288                 (void)elt;
289                 STAILQ_REMOVE_HEAD(&mp->elt_list, next);
290                 mp->populated_size--;
291         }
292
293         while (!STAILQ_EMPTY(&mp->mem_list)) {
294                 memhdr = STAILQ_FIRST(&mp->mem_list);
295                 STAILQ_REMOVE_HEAD(&mp->mem_list, next);
296                 if (memhdr->free_cb != NULL)
297                         memhdr->free_cb(memhdr, memhdr->opaque);
298                 rte_free(memhdr);
299                 mp->nb_mem_chunks--;
300         }
301 }
302
303 static int
304 mempool_ops_alloc_once(struct rte_mempool *mp)
305 {
306         int ret;
307
308         /* create the internal ring if not already done */
309         if ((mp->flags & MEMPOOL_F_POOL_CREATED) == 0) {
310                 ret = rte_mempool_ops_alloc(mp);
311                 if (ret != 0)
312                         return ret;
313                 mp->flags |= MEMPOOL_F_POOL_CREATED;
314         }
315         return 0;
316 }
317
318 /* Add objects in the pool, using a physically contiguous memory
319  * zone. Return the number of objects added, or a negative value
320  * on error.
321  */
322 int
323 rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
324         rte_iova_t iova, size_t len, rte_mempool_memchunk_free_cb_t *free_cb,
325         void *opaque)
326 {
327         unsigned i = 0;
328         size_t off;
329         struct rte_mempool_memhdr *memhdr;
330         int ret;
331
332         ret = mempool_ops_alloc_once(mp);
333         if (ret != 0)
334                 return ret;
335
336         /* mempool is already populated */
337         if (mp->populated_size >= mp->size)
338                 return -ENOSPC;
339
340         memhdr = rte_zmalloc("MEMPOOL_MEMHDR", sizeof(*memhdr), 0);
341         if (memhdr == NULL)
342                 return -ENOMEM;
343
344         memhdr->mp = mp;
345         memhdr->addr = vaddr;
346         memhdr->iova = iova;
347         memhdr->len = len;
348         memhdr->free_cb = free_cb;
349         memhdr->opaque = opaque;
350
351         if (mp->flags & MEMPOOL_F_NO_CACHE_ALIGN)
352                 off = RTE_PTR_ALIGN_CEIL(vaddr, 8) - vaddr;
353         else
354                 off = RTE_PTR_ALIGN_CEIL(vaddr, RTE_MEMPOOL_ALIGN) - vaddr;
355
356         if (off > len) {
357                 ret = 0;
358                 goto fail;
359         }
360
361         i = rte_mempool_ops_populate(mp, mp->size - mp->populated_size,
362                 (char *)vaddr + off,
363                 (iova == RTE_BAD_IOVA) ? RTE_BAD_IOVA : (iova + off),
364                 len - off, mempool_add_elem, NULL);
365
366         /* not enough room to store one object */
367         if (i == 0) {
368                 ret = 0;
369                 goto fail;
370         }
371
372         STAILQ_INSERT_TAIL(&mp->mem_list, memhdr, next);
373         mp->nb_mem_chunks++;
374
375         /* Report the mempool as ready only when fully populated. */
376         if (mp->populated_size >= mp->size)
377                 mempool_event_callback_invoke(RTE_MEMPOOL_EVENT_READY, mp);
378
379         rte_mempool_trace_populate_iova(mp, vaddr, iova, len, free_cb, opaque);
380         return i;
381
382 fail:
383         rte_free(memhdr);
384         return ret;
385 }
386
387 static rte_iova_t
388 get_iova(void *addr)
389 {
390         struct rte_memseg *ms;
391
392         /* try registered memory first */
393         ms = rte_mem_virt2memseg(addr, NULL);
394         if (ms == NULL || ms->iova == RTE_BAD_IOVA)
395                 /* fall back to actual physical address */
396                 return rte_mem_virt2iova(addr);
397         return ms->iova + RTE_PTR_DIFF(addr, ms->addr);
398 }
399
400 /* Populate the mempool with a virtual area. Return the number of
401  * objects added, or a negative value on error.
402  */
403 int
404 rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
405         size_t len, size_t pg_sz, rte_mempool_memchunk_free_cb_t *free_cb,
406         void *opaque)
407 {
408         rte_iova_t iova;
409         size_t off, phys_len;
410         int ret, cnt = 0;
411
412         if (mp->flags & MEMPOOL_F_NO_IOVA_CONTIG)
413                 return rte_mempool_populate_iova(mp, addr, RTE_BAD_IOVA,
414                         len, free_cb, opaque);
415
416         for (off = 0; off < len &&
417                      mp->populated_size < mp->size; off += phys_len) {
418
419                 iova = get_iova(addr + off);
420
421                 /* populate with the largest group of contiguous pages */
422                 for (phys_len = RTE_MIN(
423                         (size_t)(RTE_PTR_ALIGN_CEIL(addr + off + 1, pg_sz) -
424                                 (addr + off)),
425                         len - off);
426                      off + phys_len < len;
427                      phys_len = RTE_MIN(phys_len + pg_sz, len - off)) {
428                         rte_iova_t iova_tmp;
429
430                         iova_tmp = get_iova(addr + off + phys_len);
431
432                         if (iova_tmp == RTE_BAD_IOVA ||
433                                         iova_tmp != iova + phys_len)
434                                 break;
435                 }
436
437                 ret = rte_mempool_populate_iova(mp, addr + off, iova,
438                         phys_len, free_cb, opaque);
439                 if (ret == 0)
440                         continue;
441                 if (ret < 0)
442                         goto fail;
443                 /* no need to call the free callback for next chunks */
444                 free_cb = NULL;
445                 cnt += ret;
446         }
447
448         rte_mempool_trace_populate_virt(mp, addr, len, pg_sz, free_cb, opaque);
449         return cnt;
450
451  fail:
452         rte_mempool_free_memchunks(mp);
453         return ret;
454 }
455
456 /* Get the minimal page size used in a mempool before populating it. */
457 int
458 rte_mempool_get_page_size(struct rte_mempool *mp, size_t *pg_sz)
459 {
460         bool need_iova_contig_obj;
461         bool alloc_in_ext_mem;
462         int ret;
463
464         /* check if we can retrieve a valid socket ID */
465         ret = rte_malloc_heap_socket_is_external(mp->socket_id);
466         if (ret < 0)
467                 return -EINVAL;
468         alloc_in_ext_mem = (ret == 1);
469         need_iova_contig_obj = !(mp->flags & MEMPOOL_F_NO_IOVA_CONTIG);
470
471         if (!need_iova_contig_obj)
472                 *pg_sz = 0;
473         else if (rte_eal_has_hugepages() || alloc_in_ext_mem)
474                 *pg_sz = get_min_page_size(mp->socket_id);
475         else
476                 *pg_sz = rte_mem_page_size();
477
478         rte_mempool_trace_get_page_size(mp, *pg_sz);
479         return 0;
480 }
481
482 /* Default function to populate the mempool: allocate memory in memzones,
483  * and populate them. Return the number of objects added, or a negative
484  * value on error.
485  */
486 int
487 rte_mempool_populate_default(struct rte_mempool *mp)
488 {
489         unsigned int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY;
490         char mz_name[RTE_MEMZONE_NAMESIZE];
491         const struct rte_memzone *mz;
492         ssize_t mem_size;
493         size_t align, pg_sz, pg_shift = 0;
494         rte_iova_t iova;
495         unsigned mz_id, n;
496         int ret;
497         bool need_iova_contig_obj;
498         size_t max_alloc_size = SIZE_MAX;
499
500         ret = mempool_ops_alloc_once(mp);
501         if (ret != 0)
502                 return ret;
503
504         /* mempool must not be populated */
505         if (mp->nb_mem_chunks != 0)
506                 return -EEXIST;
507
508         /*
509          * the following section calculates page shift and page size values.
510          *
511          * these values impact the result of calc_mem_size operation, which
512          * returns the amount of memory that should be allocated to store the
513          * desired number of objects. when not zero, it allocates more memory
514          * for the padding between objects, to ensure that an object does not
515          * cross a page boundary. in other words, page size/shift are to be set
516          * to zero if mempool elements won't care about page boundaries.
517          * there are several considerations for page size and page shift here.
518          *
519          * if we don't need our mempools to have physically contiguous objects,
520          * then just set page shift and page size to 0, because the user has
521          * indicated that there's no need to care about anything.
522          *
523          * if we do need contiguous objects (if a mempool driver has its
524          * own calc_size() method returning min_chunk_size = mem_size),
525          * there is also an option to reserve the entire mempool memory
526          * as one contiguous block of memory.
527          *
528          * if we require contiguous objects, but not necessarily the entire
529          * mempool reserved space to be contiguous, pg_sz will be != 0,
530          * and the default ops->populate() will take care of not placing
531          * objects across pages.
532          *
533          * if our IO addresses are physical, we may get memory from bigger
534          * pages, or we might get memory from smaller pages, and how much of it
535          * we require depends on whether we want bigger or smaller pages.
536          * However, requesting each and every memory size is too much work, so
537          * what we'll do instead is walk through the page sizes available, pick
538          * the smallest one and set up page shift to match that one. We will be
539          * wasting some space this way, but it's much nicer than looping around
540          * trying to reserve each and every page size.
541          *
542          * If we fail to get enough contiguous memory, then we'll go and
543          * reserve space in smaller chunks.
544          */
545
546         need_iova_contig_obj = !(mp->flags & MEMPOOL_F_NO_IOVA_CONTIG);
547         ret = rte_mempool_get_page_size(mp, &pg_sz);
548         if (ret < 0)
549                 return ret;
550
551         if (pg_sz != 0)
552                 pg_shift = rte_bsf32(pg_sz);
553
554         for (mz_id = 0, n = mp->size; n > 0; mz_id++, n -= ret) {
555                 size_t min_chunk_size;
556
557                 mem_size = rte_mempool_ops_calc_mem_size(
558                         mp, n, pg_shift, &min_chunk_size, &align);
559
560                 if (mem_size < 0) {
561                         ret = mem_size;
562                         goto fail;
563                 }
564
565                 ret = snprintf(mz_name, sizeof(mz_name),
566                         RTE_MEMPOOL_MZ_FORMAT "_%d", mp->name, mz_id);
567                 if (ret < 0 || ret >= (int)sizeof(mz_name)) {
568                         ret = -ENAMETOOLONG;
569                         goto fail;
570                 }
571
572                 /* if we're trying to reserve contiguous memory, add appropriate
573                  * memzone flag.
574                  */
575                 if (min_chunk_size == (size_t)mem_size)
576                         mz_flags |= RTE_MEMZONE_IOVA_CONTIG;
577
578                 /* Allocate a memzone, retrying with a smaller area on ENOMEM */
579                 do {
580                         mz = rte_memzone_reserve_aligned(mz_name,
581                                 RTE_MIN((size_t)mem_size, max_alloc_size),
582                                 mp->socket_id, mz_flags, align);
583
584                         if (mz != NULL || rte_errno != ENOMEM)
585                                 break;
586
587                         max_alloc_size = RTE_MIN(max_alloc_size,
588                                                 (size_t)mem_size) / 2;
589                 } while (mz == NULL && max_alloc_size >= min_chunk_size);
590
591                 if (mz == NULL) {
592                         ret = -rte_errno;
593                         goto fail;
594                 }
595
596                 if (need_iova_contig_obj)
597                         iova = mz->iova;
598                 else
599                         iova = RTE_BAD_IOVA;
600
601                 if (pg_sz == 0 || (mz_flags & RTE_MEMZONE_IOVA_CONTIG))
602                         ret = rte_mempool_populate_iova(mp, mz->addr,
603                                 iova, mz->len,
604                                 rte_mempool_memchunk_mz_free,
605                                 (void *)(uintptr_t)mz);
606                 else
607                         ret = rte_mempool_populate_virt(mp, mz->addr,
608                                 mz->len, pg_sz,
609                                 rte_mempool_memchunk_mz_free,
610                                 (void *)(uintptr_t)mz);
611                 if (ret == 0) /* should not happen */
612                         ret = -ENOBUFS;
613                 if (ret < 0) {
614                         rte_memzone_free(mz);
615                         goto fail;
616                 }
617         }
618
619         rte_mempool_trace_populate_default(mp);
620         return mp->size;
621
622  fail:
623         rte_mempool_free_memchunks(mp);
624         return ret;
625 }
626
627 /* return the memory size required for mempool objects in anonymous mem */
628 static ssize_t
629 get_anon_size(const struct rte_mempool *mp)
630 {
631         ssize_t size;
632         size_t pg_sz, pg_shift;
633         size_t min_chunk_size;
634         size_t align;
635
636         pg_sz = rte_mem_page_size();
637         pg_shift = rte_bsf32(pg_sz);
638         size = rte_mempool_ops_calc_mem_size(mp, mp->size, pg_shift,
639                                              &min_chunk_size, &align);
640
641         return size;
642 }
643
644 /* unmap a memory zone mapped by rte_mempool_populate_anon() */
645 static void
646 rte_mempool_memchunk_anon_free(struct rte_mempool_memhdr *memhdr,
647         void *opaque)
648 {
649         ssize_t size;
650
651         /*
652          * Calculate size since memhdr->len has contiguous chunk length
653          * which may be smaller if anon map is split into many contiguous
654          * chunks. Result must be the same as we calculated on populate.
655          */
656         size = get_anon_size(memhdr->mp);
657         if (size < 0)
658                 return;
659
660         rte_mem_unmap(opaque, size);
661 }
662
663 /* populate the mempool with an anonymous mapping */
664 int
665 rte_mempool_populate_anon(struct rte_mempool *mp)
666 {
667         ssize_t size;
668         int ret;
669         char *addr;
670
671         /* mempool is already populated, error */
672         if ((!STAILQ_EMPTY(&mp->mem_list)) || mp->nb_mem_chunks != 0) {
673                 rte_errno = EINVAL;
674                 return 0;
675         }
676
677         ret = mempool_ops_alloc_once(mp);
678         if (ret < 0) {
679                 rte_errno = -ret;
680                 return 0;
681         }
682
683         size = get_anon_size(mp);
684         if (size < 0) {
685                 rte_errno = -size;
686                 return 0;
687         }
688
689         /* get chunk of virtually continuous memory */
690         addr = rte_mem_map(NULL, size, RTE_PROT_READ | RTE_PROT_WRITE,
691                 RTE_MAP_SHARED | RTE_MAP_ANONYMOUS, -1, 0);
692         if (addr == NULL)
693                 return 0;
694         /* can't use MMAP_LOCKED, it does not exist on BSD */
695         if (rte_mem_lock(addr, size) < 0) {
696                 rte_mem_unmap(addr, size);
697                 return 0;
698         }
699
700         ret = rte_mempool_populate_virt(mp, addr, size, rte_mem_page_size(),
701                 rte_mempool_memchunk_anon_free, addr);
702         if (ret == 0) /* should not happen */
703                 ret = -ENOBUFS;
704         if (ret < 0) {
705                 rte_errno = -ret;
706                 goto fail;
707         }
708
709         rte_mempool_trace_populate_anon(mp);
710         return mp->populated_size;
711
712  fail:
713         rte_mempool_free_memchunks(mp);
714         return 0;
715 }
716
717 /* free a mempool */
718 void
719 rte_mempool_free(struct rte_mempool *mp)
720 {
721         struct rte_mempool_list *mempool_list = NULL;
722         struct rte_tailq_entry *te;
723
724         if (mp == NULL)
725                 return;
726
727         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
728         rte_mcfg_tailq_write_lock();
729         /* find out tailq entry */
730         TAILQ_FOREACH(te, mempool_list, next) {
731                 if (te->data == (void *)mp)
732                         break;
733         }
734
735         if (te != NULL) {
736                 TAILQ_REMOVE(mempool_list, te, next);
737                 rte_free(te);
738         }
739         rte_mcfg_tailq_write_unlock();
740
741         mempool_event_callback_invoke(RTE_MEMPOOL_EVENT_DESTROY, mp);
742         rte_mempool_trace_free(mp);
743         rte_mempool_free_memchunks(mp);
744         rte_mempool_ops_free(mp);
745         rte_memzone_free(mp->mz);
746 }
747
748 static void
749 mempool_cache_init(struct rte_mempool_cache *cache, uint32_t size)
750 {
751         cache->size = size;
752         cache->flushthresh = CALC_CACHE_FLUSHTHRESH(size);
753         cache->len = 0;
754 }
755
756 /*
757  * Create and initialize a cache for objects that are retrieved from and
758  * returned to an underlying mempool. This structure is identical to the
759  * local_cache[lcore_id] pointed to by the mempool structure.
760  */
761 struct rte_mempool_cache *
762 rte_mempool_cache_create(uint32_t size, int socket_id)
763 {
764         struct rte_mempool_cache *cache;
765
766         if (size == 0 || size > RTE_MEMPOOL_CACHE_MAX_SIZE) {
767                 rte_errno = EINVAL;
768                 return NULL;
769         }
770
771         cache = rte_zmalloc_socket("MEMPOOL_CACHE", sizeof(*cache),
772                                   RTE_CACHE_LINE_SIZE, socket_id);
773         if (cache == NULL) {
774                 RTE_LOG(ERR, MEMPOOL, "Cannot allocate mempool cache.\n");
775                 rte_errno = ENOMEM;
776                 return NULL;
777         }
778
779         mempool_cache_init(cache, size);
780
781         rte_mempool_trace_cache_create(size, socket_id, cache);
782         return cache;
783 }
784
785 /*
786  * Free a cache. It's the responsibility of the user to make sure that any
787  * remaining objects in the cache are flushed to the corresponding
788  * mempool.
789  */
790 void
791 rte_mempool_cache_free(struct rte_mempool_cache *cache)
792 {
793         rte_mempool_trace_cache_free(cache);
794         rte_free(cache);
795 }
796
797 #define MEMPOOL_KNOWN_FLAGS (MEMPOOL_F_NO_SPREAD \
798         | MEMPOOL_F_NO_CACHE_ALIGN \
799         | MEMPOOL_F_SP_PUT \
800         | MEMPOOL_F_SC_GET \
801         | MEMPOOL_F_POOL_CREATED \
802         | MEMPOOL_F_NO_IOVA_CONTIG \
803         )
804 /* create an empty mempool */
805 struct rte_mempool *
806 rte_mempool_create_empty(const char *name, unsigned n, unsigned elt_size,
807         unsigned cache_size, unsigned private_data_size,
808         int socket_id, unsigned flags)
809 {
810         char mz_name[RTE_MEMZONE_NAMESIZE];
811         struct rte_mempool_list *mempool_list;
812         struct rte_mempool *mp = NULL;
813         struct rte_tailq_entry *te = NULL;
814         const struct rte_memzone *mz = NULL;
815         size_t mempool_size;
816         unsigned int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY;
817         struct rte_mempool_objsz objsz;
818         unsigned lcore_id;
819         int ret;
820
821         /* compilation-time checks */
822         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool) &
823                           RTE_CACHE_LINE_MASK) != 0);
824         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_cache) &
825                           RTE_CACHE_LINE_MASK) != 0);
826 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
827         RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_debug_stats) &
828                           RTE_CACHE_LINE_MASK) != 0);
829         RTE_BUILD_BUG_ON((offsetof(struct rte_mempool, stats) &
830                           RTE_CACHE_LINE_MASK) != 0);
831 #endif
832
833         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
834
835         /* asked for zero items */
836         if (n == 0) {
837                 rte_errno = EINVAL;
838                 return NULL;
839         }
840
841         /* asked cache too big */
842         if (cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE ||
843             CALC_CACHE_FLUSHTHRESH(cache_size) > n) {
844                 rte_errno = EINVAL;
845                 return NULL;
846         }
847
848         /* enforce no unknown flag is passed by the application */
849         if ((flags & ~MEMPOOL_KNOWN_FLAGS) != 0) {
850                 rte_errno = EINVAL;
851                 return NULL;
852         }
853
854         /* "no cache align" imply "no spread" */
855         if (flags & MEMPOOL_F_NO_CACHE_ALIGN)
856                 flags |= MEMPOOL_F_NO_SPREAD;
857
858         /* calculate mempool object sizes. */
859         if (!rte_mempool_calc_obj_size(elt_size, flags, &objsz)) {
860                 rte_errno = EINVAL;
861                 return NULL;
862         }
863
864         rte_mcfg_mempool_write_lock();
865
866         /*
867          * reserve a memory zone for this mempool: private data is
868          * cache-aligned
869          */
870         private_data_size = (private_data_size +
871                              RTE_MEMPOOL_ALIGN_MASK) & (~RTE_MEMPOOL_ALIGN_MASK);
872
873
874         /* try to allocate tailq entry */
875         te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
876         if (te == NULL) {
877                 RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
878                 goto exit_unlock;
879         }
880
881         mempool_size = MEMPOOL_HEADER_SIZE(mp, cache_size);
882         mempool_size += private_data_size;
883         mempool_size = RTE_ALIGN_CEIL(mempool_size, RTE_MEMPOOL_ALIGN);
884
885         ret = snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_MZ_FORMAT, name);
886         if (ret < 0 || ret >= (int)sizeof(mz_name)) {
887                 rte_errno = ENAMETOOLONG;
888                 goto exit_unlock;
889         }
890
891         mz = rte_memzone_reserve(mz_name, mempool_size, socket_id, mz_flags);
892         if (mz == NULL)
893                 goto exit_unlock;
894
895         /* init the mempool structure */
896         mp = mz->addr;
897         memset(mp, 0, MEMPOOL_HEADER_SIZE(mp, cache_size));
898         ret = strlcpy(mp->name, name, sizeof(mp->name));
899         if (ret < 0 || ret >= (int)sizeof(mp->name)) {
900                 rte_errno = ENAMETOOLONG;
901                 goto exit_unlock;
902         }
903         mp->mz = mz;
904         mp->size = n;
905         mp->flags = flags;
906         mp->socket_id = socket_id;
907         mp->elt_size = objsz.elt_size;
908         mp->header_size = objsz.header_size;
909         mp->trailer_size = objsz.trailer_size;
910         /* Size of default caches, zero means disabled. */
911         mp->cache_size = cache_size;
912         mp->private_data_size = private_data_size;
913         STAILQ_INIT(&mp->elt_list);
914         STAILQ_INIT(&mp->mem_list);
915
916         /*
917          * local_cache pointer is set even if cache_size is zero.
918          * The local_cache points to just past the elt_pa[] array.
919          */
920         mp->local_cache = (struct rte_mempool_cache *)
921                 RTE_PTR_ADD(mp, MEMPOOL_HEADER_SIZE(mp, 0));
922
923         /* Init all default caches. */
924         if (cache_size != 0) {
925                 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++)
926                         mempool_cache_init(&mp->local_cache[lcore_id],
927                                            cache_size);
928         }
929
930         te->data = mp;
931
932         rte_mcfg_tailq_write_lock();
933         TAILQ_INSERT_TAIL(mempool_list, te, next);
934         rte_mcfg_tailq_write_unlock();
935         rte_mcfg_mempool_write_unlock();
936
937         rte_mempool_trace_create_empty(name, n, elt_size, cache_size,
938                 private_data_size, flags, mp);
939         return mp;
940
941 exit_unlock:
942         rte_mcfg_mempool_write_unlock();
943         rte_free(te);
944         rte_mempool_free(mp);
945         return NULL;
946 }
947
948 /* create the mempool */
949 struct rte_mempool *
950 rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
951         unsigned cache_size, unsigned private_data_size,
952         rte_mempool_ctor_t *mp_init, void *mp_init_arg,
953         rte_mempool_obj_cb_t *obj_init, void *obj_init_arg,
954         int socket_id, unsigned flags)
955 {
956         int ret;
957         struct rte_mempool *mp;
958
959         mp = rte_mempool_create_empty(name, n, elt_size, cache_size,
960                 private_data_size, socket_id, flags);
961         if (mp == NULL)
962                 return NULL;
963
964         /*
965          * Since we have 4 combinations of the SP/SC/MP/MC examine the flags to
966          * set the correct index into the table of ops structs.
967          */
968         if ((flags & MEMPOOL_F_SP_PUT) && (flags & MEMPOOL_F_SC_GET))
969                 ret = rte_mempool_set_ops_byname(mp, "ring_sp_sc", NULL);
970         else if (flags & MEMPOOL_F_SP_PUT)
971                 ret = rte_mempool_set_ops_byname(mp, "ring_sp_mc", NULL);
972         else if (flags & MEMPOOL_F_SC_GET)
973                 ret = rte_mempool_set_ops_byname(mp, "ring_mp_sc", NULL);
974         else
975                 ret = rte_mempool_set_ops_byname(mp, "ring_mp_mc", NULL);
976
977         if (ret)
978                 goto fail;
979
980         /* call the mempool priv initializer */
981         if (mp_init)
982                 mp_init(mp, mp_init_arg);
983
984         if (rte_mempool_populate_default(mp) < 0)
985                 goto fail;
986
987         /* call the object initializers */
988         if (obj_init)
989                 rte_mempool_obj_iter(mp, obj_init, obj_init_arg);
990
991         rte_mempool_trace_create(name, n, elt_size, cache_size,
992                 private_data_size, mp_init, mp_init_arg, obj_init,
993                 obj_init_arg, flags, mp);
994         return mp;
995
996  fail:
997         rte_mempool_free(mp);
998         return NULL;
999 }
1000
1001 /* Return the number of entries in the mempool */
1002 unsigned int
1003 rte_mempool_avail_count(const struct rte_mempool *mp)
1004 {
1005         unsigned count;
1006         unsigned lcore_id;
1007
1008         count = rte_mempool_ops_get_count(mp);
1009
1010         if (mp->cache_size == 0)
1011                 return count;
1012
1013         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++)
1014                 count += mp->local_cache[lcore_id].len;
1015
1016         /*
1017          * due to race condition (access to len is not locked), the
1018          * total can be greater than size... so fix the result
1019          */
1020         if (count > mp->size)
1021                 return mp->size;
1022         return count;
1023 }
1024
1025 /* return the number of entries allocated from the mempool */
1026 unsigned int
1027 rte_mempool_in_use_count(const struct rte_mempool *mp)
1028 {
1029         return mp->size - rte_mempool_avail_count(mp);
1030 }
1031
1032 /* dump the cache status */
1033 static unsigned
1034 rte_mempool_dump_cache(FILE *f, const struct rte_mempool *mp)
1035 {
1036         unsigned lcore_id;
1037         unsigned count = 0;
1038         unsigned cache_count;
1039
1040         fprintf(f, "  internal cache infos:\n");
1041         fprintf(f, "    cache_size=%"PRIu32"\n", mp->cache_size);
1042
1043         if (mp->cache_size == 0)
1044                 return count;
1045
1046         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1047                 cache_count = mp->local_cache[lcore_id].len;
1048                 fprintf(f, "    cache_count[%u]=%"PRIu32"\n",
1049                         lcore_id, cache_count);
1050                 count += cache_count;
1051         }
1052         fprintf(f, "    total_cache_count=%u\n", count);
1053         return count;
1054 }
1055
1056 #ifndef __INTEL_COMPILER
1057 #pragma GCC diagnostic ignored "-Wcast-qual"
1058 #endif
1059
1060 /* check and update cookies or panic (internal) */
1061 void rte_mempool_check_cookies(const struct rte_mempool *mp,
1062         void * const *obj_table_const, unsigned n, int free)
1063 {
1064 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1065         struct rte_mempool_objhdr *hdr;
1066         struct rte_mempool_objtlr *tlr;
1067         uint64_t cookie;
1068         void *tmp;
1069         void *obj;
1070         void **obj_table;
1071
1072         /* Force to drop the "const" attribute. This is done only when
1073          * DEBUG is enabled */
1074         tmp = (void *) obj_table_const;
1075         obj_table = tmp;
1076
1077         while (n--) {
1078                 obj = obj_table[n];
1079
1080                 if (rte_mempool_from_obj(obj) != mp)
1081                         rte_panic("MEMPOOL: object is owned by another "
1082                                   "mempool\n");
1083
1084                 hdr = __mempool_get_header(obj);
1085                 cookie = hdr->cookie;
1086
1087                 if (free == 0) {
1088                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE1) {
1089                                 RTE_LOG(CRIT, MEMPOOL,
1090                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
1091                                         obj, (const void *) mp, cookie);
1092                                 rte_panic("MEMPOOL: bad header cookie (put)\n");
1093                         }
1094                         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2;
1095                 } else if (free == 1) {
1096                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE2) {
1097                                 RTE_LOG(CRIT, MEMPOOL,
1098                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
1099                                         obj, (const void *) mp, cookie);
1100                                 rte_panic("MEMPOOL: bad header cookie (get)\n");
1101                         }
1102                         hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE1;
1103                 } else if (free == 2) {
1104                         if (cookie != RTE_MEMPOOL_HEADER_COOKIE1 &&
1105                             cookie != RTE_MEMPOOL_HEADER_COOKIE2) {
1106                                 RTE_LOG(CRIT, MEMPOOL,
1107                                         "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
1108                                         obj, (const void *) mp, cookie);
1109                                 rte_panic("MEMPOOL: bad header cookie (audit)\n");
1110                         }
1111                 }
1112                 tlr = __mempool_get_trailer(obj);
1113                 cookie = tlr->cookie;
1114                 if (cookie != RTE_MEMPOOL_TRAILER_COOKIE) {
1115                         RTE_LOG(CRIT, MEMPOOL,
1116                                 "obj=%p, mempool=%p, cookie=%" PRIx64 "\n",
1117                                 obj, (const void *) mp, cookie);
1118                         rte_panic("MEMPOOL: bad trailer cookie\n");
1119                 }
1120         }
1121 #else
1122         RTE_SET_USED(mp);
1123         RTE_SET_USED(obj_table_const);
1124         RTE_SET_USED(n);
1125         RTE_SET_USED(free);
1126 #endif
1127 }
1128
1129 void
1130 rte_mempool_contig_blocks_check_cookies(const struct rte_mempool *mp,
1131         void * const *first_obj_table_const, unsigned int n, int free)
1132 {
1133 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1134         struct rte_mempool_info info;
1135         const size_t total_elt_sz =
1136                 mp->header_size + mp->elt_size + mp->trailer_size;
1137         unsigned int i, j;
1138
1139         rte_mempool_ops_get_info(mp, &info);
1140
1141         for (i = 0; i < n; ++i) {
1142                 void *first_obj = first_obj_table_const[i];
1143
1144                 for (j = 0; j < info.contig_block_size; ++j) {
1145                         void *obj;
1146
1147                         obj = (void *)((uintptr_t)first_obj + j * total_elt_sz);
1148                         rte_mempool_check_cookies(mp, &obj, 1, free);
1149                 }
1150         }
1151 #else
1152         RTE_SET_USED(mp);
1153         RTE_SET_USED(first_obj_table_const);
1154         RTE_SET_USED(n);
1155         RTE_SET_USED(free);
1156 #endif
1157 }
1158
1159 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1160 static void
1161 mempool_obj_audit(struct rte_mempool *mp, __rte_unused void *opaque,
1162         void *obj, __rte_unused unsigned idx)
1163 {
1164         __mempool_check_cookies(mp, &obj, 1, 2);
1165 }
1166
1167 static void
1168 mempool_audit_cookies(struct rte_mempool *mp)
1169 {
1170         unsigned num;
1171
1172         num = rte_mempool_obj_iter(mp, mempool_obj_audit, NULL);
1173         if (num != mp->size) {
1174                 rte_panic("rte_mempool_obj_iter(mempool=%p, size=%u) "
1175                         "iterated only over %u elements\n",
1176                         mp, mp->size, num);
1177         }
1178 }
1179 #else
1180 #define mempool_audit_cookies(mp) do {} while(0)
1181 #endif
1182
1183 #ifndef __INTEL_COMPILER
1184 #pragma GCC diagnostic error "-Wcast-qual"
1185 #endif
1186
1187 /* check cookies before and after objects */
1188 static void
1189 mempool_audit_cache(const struct rte_mempool *mp)
1190 {
1191         /* check cache size consistency */
1192         unsigned lcore_id;
1193
1194         if (mp->cache_size == 0)
1195                 return;
1196
1197         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1198                 const struct rte_mempool_cache *cache;
1199                 cache = &mp->local_cache[lcore_id];
1200                 if (cache->len > RTE_DIM(cache->objs)) {
1201                         RTE_LOG(CRIT, MEMPOOL, "badness on cache[%u]\n",
1202                                 lcore_id);
1203                         rte_panic("MEMPOOL: invalid cache len\n");
1204                 }
1205         }
1206 }
1207
1208 /* check the consistency of mempool (size, cookies, ...) */
1209 void
1210 rte_mempool_audit(struct rte_mempool *mp)
1211 {
1212         mempool_audit_cache(mp);
1213         mempool_audit_cookies(mp);
1214
1215         /* For case where mempool DEBUG is not set, and cache size is 0 */
1216         RTE_SET_USED(mp);
1217 }
1218
1219 /* dump the status of the mempool on the console */
1220 void
1221 rte_mempool_dump(FILE *f, struct rte_mempool *mp)
1222 {
1223 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1224         struct rte_mempool_info info;
1225         struct rte_mempool_debug_stats sum;
1226         unsigned lcore_id;
1227 #endif
1228         struct rte_mempool_memhdr *memhdr;
1229         struct rte_mempool_ops *ops;
1230         unsigned common_count;
1231         unsigned cache_count;
1232         size_t mem_len = 0;
1233
1234         RTE_ASSERT(f != NULL);
1235         RTE_ASSERT(mp != NULL);
1236
1237         fprintf(f, "mempool <%s>@%p\n", mp->name, mp);
1238         fprintf(f, "  flags=%x\n", mp->flags);
1239         fprintf(f, "  socket_id=%d\n", mp->socket_id);
1240         fprintf(f, "  pool=%p\n", mp->pool_data);
1241         fprintf(f, "  iova=0x%" PRIx64 "\n", mp->mz->iova);
1242         fprintf(f, "  nb_mem_chunks=%u\n", mp->nb_mem_chunks);
1243         fprintf(f, "  size=%"PRIu32"\n", mp->size);
1244         fprintf(f, "  populated_size=%"PRIu32"\n", mp->populated_size);
1245         fprintf(f, "  header_size=%"PRIu32"\n", mp->header_size);
1246         fprintf(f, "  elt_size=%"PRIu32"\n", mp->elt_size);
1247         fprintf(f, "  trailer_size=%"PRIu32"\n", mp->trailer_size);
1248         fprintf(f, "  total_obj_size=%"PRIu32"\n",
1249                mp->header_size + mp->elt_size + mp->trailer_size);
1250
1251         fprintf(f, "  private_data_size=%"PRIu32"\n", mp->private_data_size);
1252
1253         fprintf(f, "  ops_index=%d\n", mp->ops_index);
1254         ops = rte_mempool_get_ops(mp->ops_index);
1255         fprintf(f, "  ops_name: <%s>\n", (ops != NULL) ? ops->name : "NA");
1256
1257         STAILQ_FOREACH(memhdr, &mp->mem_list, next)
1258                 mem_len += memhdr->len;
1259         if (mem_len != 0) {
1260                 fprintf(f, "  avg bytes/object=%#Lf\n",
1261                         (long double)mem_len / mp->size);
1262         }
1263
1264         cache_count = rte_mempool_dump_cache(f, mp);
1265         common_count = rte_mempool_ops_get_count(mp);
1266         if ((cache_count + common_count) > mp->size)
1267                 common_count = mp->size - cache_count;
1268         fprintf(f, "  common_pool_count=%u\n", common_count);
1269
1270         /* sum and dump statistics */
1271 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1272         rte_mempool_ops_get_info(mp, &info);
1273         memset(&sum, 0, sizeof(sum));
1274         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1275                 sum.put_bulk += mp->stats[lcore_id].put_bulk;
1276                 sum.put_objs += mp->stats[lcore_id].put_objs;
1277                 sum.put_common_pool_bulk += mp->stats[lcore_id].put_common_pool_bulk;
1278                 sum.put_common_pool_objs += mp->stats[lcore_id].put_common_pool_objs;
1279                 sum.get_common_pool_bulk += mp->stats[lcore_id].get_common_pool_bulk;
1280                 sum.get_common_pool_objs += mp->stats[lcore_id].get_common_pool_objs;
1281                 sum.get_success_bulk += mp->stats[lcore_id].get_success_bulk;
1282                 sum.get_success_objs += mp->stats[lcore_id].get_success_objs;
1283                 sum.get_fail_bulk += mp->stats[lcore_id].get_fail_bulk;
1284                 sum.get_fail_objs += mp->stats[lcore_id].get_fail_objs;
1285                 sum.get_success_blks += mp->stats[lcore_id].get_success_blks;
1286                 sum.get_fail_blks += mp->stats[lcore_id].get_fail_blks;
1287         }
1288         fprintf(f, "  stats:\n");
1289         fprintf(f, "    put_bulk=%"PRIu64"\n", sum.put_bulk);
1290         fprintf(f, "    put_objs=%"PRIu64"\n", sum.put_objs);
1291         fprintf(f, "    put_common_pool_bulk=%"PRIu64"\n", sum.put_common_pool_bulk);
1292         fprintf(f, "    put_common_pool_objs=%"PRIu64"\n", sum.put_common_pool_objs);
1293         fprintf(f, "    get_common_pool_bulk=%"PRIu64"\n", sum.get_common_pool_bulk);
1294         fprintf(f, "    get_common_pool_objs=%"PRIu64"\n", sum.get_common_pool_objs);
1295         fprintf(f, "    get_success_bulk=%"PRIu64"\n", sum.get_success_bulk);
1296         fprintf(f, "    get_success_objs=%"PRIu64"\n", sum.get_success_objs);
1297         fprintf(f, "    get_fail_bulk=%"PRIu64"\n", sum.get_fail_bulk);
1298         fprintf(f, "    get_fail_objs=%"PRIu64"\n", sum.get_fail_objs);
1299         if (info.contig_block_size > 0) {
1300                 fprintf(f, "    get_success_blks=%"PRIu64"\n",
1301                         sum.get_success_blks);
1302                 fprintf(f, "    get_fail_blks=%"PRIu64"\n", sum.get_fail_blks);
1303         }
1304 #else
1305         fprintf(f, "  no statistics available\n");
1306 #endif
1307
1308         rte_mempool_audit(mp);
1309 }
1310
1311 /* dump the status of all mempools on the console */
1312 void
1313 rte_mempool_list_dump(FILE *f)
1314 {
1315         struct rte_mempool *mp = NULL;
1316         struct rte_tailq_entry *te;
1317         struct rte_mempool_list *mempool_list;
1318
1319         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
1320
1321         rte_mcfg_mempool_read_lock();
1322
1323         TAILQ_FOREACH(te, mempool_list, next) {
1324                 mp = (struct rte_mempool *) te->data;
1325                 rte_mempool_dump(f, mp);
1326         }
1327
1328         rte_mcfg_mempool_read_unlock();
1329 }
1330
1331 /* search a mempool from its name */
1332 struct rte_mempool *
1333 rte_mempool_lookup(const char *name)
1334 {
1335         struct rte_mempool *mp = NULL;
1336         struct rte_tailq_entry *te;
1337         struct rte_mempool_list *mempool_list;
1338
1339         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
1340
1341         rte_mcfg_mempool_read_lock();
1342
1343         TAILQ_FOREACH(te, mempool_list, next) {
1344                 mp = (struct rte_mempool *) te->data;
1345                 if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
1346                         break;
1347         }
1348
1349         rte_mcfg_mempool_read_unlock();
1350
1351         if (te == NULL) {
1352                 rte_errno = ENOENT;
1353                 return NULL;
1354         }
1355
1356         return mp;
1357 }
1358
1359 void rte_mempool_walk(void (*func)(struct rte_mempool *, void *),
1360                       void *arg)
1361 {
1362         struct rte_tailq_entry *te = NULL;
1363         struct rte_mempool_list *mempool_list;
1364         void *tmp_te;
1365
1366         mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list);
1367
1368         rte_mcfg_mempool_read_lock();
1369
1370         RTE_TAILQ_FOREACH_SAFE(te, mempool_list, next, tmp_te) {
1371                 (*func)((struct rte_mempool *) te->data, arg);
1372         }
1373
1374         rte_mcfg_mempool_read_unlock();
1375 }
1376
1377 struct mempool_callback_data {
1378         rte_mempool_event_callback *func;
1379         void *user_data;
1380 };
1381
1382 static void
1383 mempool_event_callback_invoke(enum rte_mempool_event event,
1384                               struct rte_mempool *mp)
1385 {
1386         struct mempool_callback_list *list;
1387         struct rte_tailq_entry *te;
1388         void *tmp_te;
1389
1390         rte_mcfg_tailq_read_lock();
1391         list = RTE_TAILQ_CAST(callback_tailq.head, mempool_callback_list);
1392         RTE_TAILQ_FOREACH_SAFE(te, list, next, tmp_te) {
1393                 struct mempool_callback_data *cb = te->data;
1394                 rte_mcfg_tailq_read_unlock();
1395                 cb->func(event, mp, cb->user_data);
1396                 rte_mcfg_tailq_read_lock();
1397         }
1398         rte_mcfg_tailq_read_unlock();
1399 }
1400
1401 int
1402 rte_mempool_event_callback_register(rte_mempool_event_callback *func,
1403                                     void *user_data)
1404 {
1405         struct mempool_callback_list *list;
1406         struct rte_tailq_entry *te = NULL;
1407         struct mempool_callback_data *cb;
1408         void *tmp_te;
1409         int ret;
1410
1411         if (func == NULL) {
1412                 rte_errno = EINVAL;
1413                 return -rte_errno;
1414         }
1415
1416         rte_mcfg_tailq_write_lock();
1417         list = RTE_TAILQ_CAST(callback_tailq.head, mempool_callback_list);
1418         RTE_TAILQ_FOREACH_SAFE(te, list, next, tmp_te) {
1419                 cb = te->data;
1420                 if (cb->func == func && cb->user_data == user_data) {
1421                         ret = -EEXIST;
1422                         goto exit;
1423                 }
1424         }
1425
1426         te = rte_zmalloc("mempool_cb_tail_entry", sizeof(*te), 0);
1427         if (te == NULL) {
1428                 RTE_LOG(ERR, MEMPOOL,
1429                         "Cannot allocate event callback tailq entry!\n");
1430                 ret = -ENOMEM;
1431                 goto exit;
1432         }
1433
1434         cb = rte_malloc("mempool_cb_data", sizeof(*cb), 0);
1435         if (cb == NULL) {
1436                 RTE_LOG(ERR, MEMPOOL,
1437                         "Cannot allocate event callback!\n");
1438                 rte_free(te);
1439                 ret = -ENOMEM;
1440                 goto exit;
1441         }
1442
1443         cb->func = func;
1444         cb->user_data = user_data;
1445         te->data = cb;
1446         TAILQ_INSERT_TAIL(list, te, next);
1447         ret = 0;
1448
1449 exit:
1450         rte_mcfg_tailq_write_unlock();
1451         rte_errno = -ret;
1452         return ret;
1453 }
1454
1455 int
1456 rte_mempool_event_callback_unregister(rte_mempool_event_callback *func,
1457                                       void *user_data)
1458 {
1459         struct mempool_callback_list *list;
1460         struct rte_tailq_entry *te = NULL;
1461         struct mempool_callback_data *cb;
1462         int ret = -ENOENT;
1463
1464         rte_mcfg_tailq_write_lock();
1465         list = RTE_TAILQ_CAST(callback_tailq.head, mempool_callback_list);
1466         TAILQ_FOREACH(te, list, next) {
1467                 cb = te->data;
1468                 if (cb->func == func && cb->user_data == user_data) {
1469                         TAILQ_REMOVE(list, te, next);
1470                         ret = 0;
1471                         break;
1472                 }
1473         }
1474         rte_mcfg_tailq_write_unlock();
1475
1476         if (ret == 0) {
1477                 rte_free(te);
1478                 rte_free(cb);
1479         }
1480         rte_errno = -ret;
1481         return ret;
1482 }