DPDK patches and discussions
 help / color / mirror / Atom feed
From: Anatoly Burakov <anatoly.burakov@intel.com>
To: dev@dpdk.org
Cc: Bruce Richardson <bruce.richardson@intel.com>,
	keith.wiles@intel.com, jianfeng.tan@intel.com,
	andras.kovacs@ericsson.com, laszlo.vadkeri@ericsson.com,
	benjamin.walker@intel.com, thomas@monjalon.net,
	konstantin.ananyev@intel.com,
	kuralamudhan.ramakrishnan@intel.com, louise.m.daly@intel.com,
	nelio.laranjeiro@6wind.com, yskoh@mellanox.com, pepperjo@japf.ch,
	jerin.jacob@caviumnetworks.com, hemant.agrawal@nxp.com,
	olivier.matz@6wind.com
Subject: [dpdk-dev] [PATCH 28/41] eal: add support for multiprocess memory hotplug
Date: Sat,  3 Mar 2018 13:46:16 +0000	[thread overview]
Message-ID: <397814e6beaa81d1b3c598477b4984c59d9746c7.1520083504.git.anatoly.burakov@intel.com> (raw)
In-Reply-To: <cover.1520083504.git.anatoly.burakov@intel.com>
In-Reply-To: <cover.1520083504.git.anatoly.burakov@intel.com>

This enables multiprocess synchronization for memory hotplug
requests at runtime (as opposed to initialization).

Basic workflow is the following. Primary process always does initial
mapping and unmapping, and secondary processes always follow primary
page map. Only one allocation request can be active at any one time.

When primary allocates memory, it ensures that all other processes
have allocated the same set of hugepages successfully, otherwise
any allocations made are being rolled back, and heap is freed back.
Heap is locked throughout the process, so no race conditions can
happen.

When primary frees memory, it frees the heap, deallocates affected
pages, and notifies other processes of deallocations. Since heap is
freed from that memory chunk, the area basically becomes invisible
to other processes even if they happen to fail to unmap that
specific set of pages, so it's completely safe to ignore results of
sync requests.

When secondary allocates memory, it does not do so by itself.
Instead, it sends a request to primary process to try and allocate
pages of specified size and on specified socket, such that a
specified heap allocation request could complete. Primary process
then sends all secondaries (including the requestor) a separate
notification of allocated pages, and expects all secondary
processes to report success before considering pages as "allocated".

Only after primary process ensures that all memory has been
successfully allocated in all secondary process, it will respond
positively to the initial request, and let secondary proceed with
the allocation. Since the heap now has memory that can satisfy
allocation request, and it was locked all this time (so no other
allocations could take place), secondary process will be able to
allocate memory from the heap.

When secondary frees memory, it hides pages to be deallocated from
the heap. Then, it sends a deallocation request to primary process,
so that it deallocates pages itself, and then sends a separate sync
request to all other processes (including the requestor) to unmap
the same pages. This way, even if secondary fails to notify other
processes of this deallocation, that memory will become invisible
to other processes, and will not be allocated from again.

So, to summarize: address space will only become part of the heap
if primary process can ensure that all other processes have
allocated this memory successfully. If anything goes wrong, the
worst thing that could happen is that a page will "leak" and will
not be available to neither DPDK nor the system, as some process
will still hold onto it. It's not an actual leak, as we can account
for the page - it's just that none of the processes will be able
to use this page for anything useful, until it gets allocated from
by the primary.

Due to underlying DPDK IPC implementation being single-threaded,
some asynchronous magic had to be done, as we need to complete
several requests before we can definitively allow secondary process
to use allocated memory (namely, it has to be present in all other
secondary processes before it can be used). Additionally, only
one allocation request is allowed to be submitted at once.

Memory allocation requests are only allowed when there are no
secondary processes currently initializing. To enforce that,
a shared rwlock is used, that is set to read lock on init (so that
several secondaries could initialize concurrently), and write lock
on making allocation requests (so that either secondary init will
have to wait, or allocation request will have to wait until all
processes have initialized).

To reduce possibility of not releasing lock on fail to init,
replace all rte_panic's with init alert followed by a return -1.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---

Notes:
    This problem is evidently complex to solve without multithreaded
    IPC implementation. An alternative approach would be to process
    each individual message in its own thread (or at least spawn a
    thread per incoming request) - that way, we can send requests
    while responding to another request, and this problem becomes
    trivial to solve (and in fact it was solved that way initially,
    before my aversion to certain other programming languages kicked
    in).
    
    Is the added complexity worth saving a couple of thread spin-ups
    here and there?

 lib/librte_eal/bsdapp/eal/Makefile                |   1 +
 lib/librte_eal/common/include/rte_eal_memconfig.h |   3 +
 lib/librte_eal/common/malloc_heap.c               | 250 ++++++--
 lib/librte_eal/common/malloc_mp.c                 | 723 ++++++++++++++++++++++
 lib/librte_eal/common/malloc_mp.h                 |  86 +++
 lib/librte_eal/common/meson.build                 |   1 +
 lib/librte_eal/linuxapp/eal/Makefile              |   1 +
 lib/librte_eal/linuxapp/eal/eal.c                 |  50 +-
 8 files changed, 1054 insertions(+), 61 deletions(-)
 create mode 100644 lib/librte_eal/common/malloc_mp.c
 create mode 100644 lib/librte_eal/common/malloc_mp.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 907e30d..250d5c1 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -59,6 +59,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_fbarray.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_malloc.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_elem.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_heap.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_mp.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_keepalive.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_service.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_reciprocal.c
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index d653d57..c4b36f6 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -60,6 +60,9 @@ struct rte_mem_config {
 	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
 	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
 
+	rte_rwlock_t memory_hotplug_lock;
+	/**< indicates whether memory hotplug request is in progress. */
+
 	/* memory segments and zones */
 	struct rte_fbarray memzones; /**< Memzone descriptors. */
 
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 7a3d0f3..9109555 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -10,6 +10,7 @@
 #include <sys/queue.h>
 
 #include <rte_memory.h>
+#include <rte_errno.h>
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
 #include <rte_launch.h>
@@ -26,6 +27,7 @@
 #include "eal_memalloc.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
+#include "malloc_mp.h"
 
 static unsigned
 check_hugepage_sz(unsigned flags, uint64_t hugepage_sz)
@@ -81,8 +83,6 @@ malloc_heap_add_memory(struct malloc_heap *heap, struct rte_memseg_list *msl,
 
 	malloc_elem_free_list_insert(elem);
 
-	heap->total_size += len;
-
 	return elem;
 }
 
@@ -146,33 +146,42 @@ heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size,
 	return elem == NULL ? NULL : (void *)(&elem[1]);
 }
 
-static int
-try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
+/* this function is exposed in malloc_mp.h */
+void
+rollback_expand_heap(struct rte_memseg **ms, int n_pages,
+		struct malloc_elem *elem, void *map_addr, size_t map_len)
+{
+	int i;
+
+	if (elem != NULL) {
+		malloc_elem_free_list_remove(elem);
+		malloc_elem_hide_region(elem, map_addr, map_len);
+	}
+
+	for (i = 0; i < n_pages; i++)
+		eal_memalloc_free_page(ms[i]);
+}
+
+/* this function is exposed in malloc_mp.h */
+struct malloc_elem *
+alloc_pages_on_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
 		int socket, unsigned int flags, size_t align, size_t bound,
-		bool contig)
+		bool contig, struct rte_memseg **ms, int n_pages)
 {
 	size_t map_len, data_start_offset;
 	struct rte_memseg_list *msl;
-	struct rte_memseg **ms;
-	struct malloc_elem *elem;
-	int i, n_pages, allocd_pages;
+	struct malloc_elem *elem = NULL;
+	int allocd_pages;
 	void *ret, *map_addr, *data_start;
 
-	align = RTE_MAX(align, MALLOC_ELEM_HEADER_LEN);
-	map_len = RTE_ALIGN_CEIL(align + elt_size + MALLOC_ELEM_TRAILER_LEN,
-			pg_sz);
-
-	n_pages = map_len / pg_sz;
+	map_len = n_pages * pg_sz;
 
-	/* we can't know in advance how many pages we'll need, so malloc */
-	ms = malloc(sizeof(*ms) * n_pages);
-
-	allocd_pages = eal_memalloc_alloc_page_bulk(ms, n_pages, pg_sz, socket,
-			true);
+	allocd_pages = eal_memalloc_alloc_page_bulk(ms, n_pages, pg_sz,
+			socket, true);
 
 	/* make sure we've allocated our pages... */
 	if (allocd_pages != n_pages)
-		goto free_ms;
+		return NULL;
 
 	map_addr = ms[0]->addr;
 	msl = rte_mem_virt2memseg_list(map_addr);
@@ -184,7 +193,7 @@ try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
 			n_pages * msl->hugepage_sz)) {
 		RTE_LOG(DEBUG, EAL, "%s(): couldn't allocate physically contiguous space\n",
 				__func__);
-		goto free_pages;
+		goto fail;
 	}
 
 	/* add newly minted memsegs to malloc heap */
@@ -195,7 +204,53 @@ try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
 			contig);
 
 	if (ret == NULL)
+		goto fail;
+
+	return elem;
+
+fail:
+	rollback_expand_heap(ms, n_pages, elem, map_addr, map_len);
+	return NULL;
+}
+
+static int
+try_expand_heap_primary(struct malloc_heap *heap, uint64_t pg_sz,
+		size_t elt_size, int socket, unsigned int flags, size_t align,
+		size_t bound, bool contig)
+{
+	struct malloc_elem *elem;
+	struct rte_memseg **ms;
+	void *map_addr;
+	size_t map_len;
+	int n_pages;
+
+	map_len = RTE_ALIGN_CEIL(align + elt_size +
+			MALLOC_ELEM_TRAILER_LEN, pg_sz);
+	n_pages = map_len / pg_sz;
+
+	/* we can't know in advance how many pages we'll need, so we malloc */
+	ms = malloc(sizeof(*ms) * n_pages);
+
+	if (ms == NULL)
+		return -1;
+
+	elem = alloc_pages_on_heap(heap, pg_sz, elt_size, socket, flags, align,
+			bound, contig, ms, n_pages);
+
+	if (elem == NULL)
+		goto free_ms;
+
+	map_addr = ms[0]->addr;
+
+	/* notify other processes that this has happened */
+	if (request_sync()) {
+		/* we couldn't ensure all processes have mapped memory,
+		 * so free it back and notify everyone that it's been
+		 * freed back.
+		 */
 		goto free_elem;
+	}
+	heap->total_size += map_len;
 
 	RTE_LOG(DEBUG, EAL, "Heap on socket %d was expanded by %zdMB\n",
 		socket, map_len >> 20ULL);
@@ -205,13 +260,9 @@ try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
 	return 0;
 
 free_elem:
-	malloc_elem_free_list_remove(elem);
-	malloc_elem_hide_region(elem, map_addr, map_len);
-	heap->total_size -= map_len;
+	rollback_expand_heap(ms, n_pages, elem, map_addr, map_len);
 
-free_pages:
-	for (i = 0; i < n_pages; i++)
-		eal_memalloc_free_page(ms[i]);
+	request_sync();
 free_ms:
 	free(ms);
 
@@ -219,6 +270,57 @@ try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
 }
 
 static int
+try_expand_heap_secondary(struct malloc_heap *heap, uint64_t pg_sz,
+		size_t elt_size, int socket, unsigned int flags, size_t align,
+		size_t bound, bool contig)
+{
+	struct malloc_mp_req req;
+	int req_result;
+
+	req.t = REQ_TYPE_ALLOC;
+	req.alloc_req.align = align;
+	req.alloc_req.bound = bound;
+	req.alloc_req.contig = contig;
+	req.alloc_req.flags = flags;
+	req.alloc_req.elt_size = elt_size;
+	req.alloc_req.page_sz = pg_sz;
+	req.alloc_req.socket = socket;
+	req.alloc_req.heap = heap; /* it's in shared memory */
+
+	req_result = request_to_primary(&req);
+
+	if (req_result != 0)
+		return -1;
+
+	if (req.result != REQ_RESULT_SUCCESS)
+		return -1;
+
+	return 0;
+}
+
+static int
+try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
+		int socket, unsigned int flags, size_t align, size_t bound,
+		bool contig)
+{
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+	int ret;
+
+	rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		ret = try_expand_heap_primary(heap, pg_sz, elt_size, socket,
+				flags, align, bound, contig);
+	} else {
+		ret = try_expand_heap_secondary(heap, pg_sz, elt_size, socket,
+				flags, align, bound, contig);
+	}
+
+	rte_rwlock_write_unlock(&mcfg->memory_hotplug_lock);
+	return ret;
+}
+
+static int
 compare_pagesz(const void *a, const void *b)
 {
 	const struct rte_memseg_list * const*mpa = a;
@@ -236,11 +338,10 @@ compare_pagesz(const void *a, const void *b)
 }
 
 static int
-alloc_mem_on_socket(size_t size, int socket, unsigned int flags, size_t align,
-		size_t bound, bool contig)
+alloc_more_mem_on_socket(struct malloc_heap *heap, size_t size, int socket,
+		unsigned int flags, size_t align, size_t bound, bool contig)
 {
 	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
-	struct malloc_heap *heap = &mcfg->malloc_heaps[socket];
 	struct rte_memseg_list *requested_msls[RTE_MAX_MEMSEG_LISTS];
 	struct rte_memseg_list *other_msls[RTE_MAX_MEMSEG_LISTS];
 	uint64_t requested_pg_sz[RTE_MAX_MEMSEG_LISTS];
@@ -355,7 +456,7 @@ heap_alloc_on_socket(const char *type, size_t size, int socket,
 
 	rte_spinlock_lock(&(heap->lock));
 
-	align = align == 0 ? 1 : align;
+	align = RTE_MAX(align == 0 ? 1 : align, MALLOC_ELEM_HEADER_LEN);
 
 	/* for legacy mode, try once and with all flags */
 	if (internal_config.legacy_mem) {
@@ -372,7 +473,8 @@ heap_alloc_on_socket(const char *type, size_t size, int socket,
 	if (ret != NULL)
 		goto alloc_unlock;
 
-	if (!alloc_mem_on_socket(size, socket, flags, align, bound, contig)) {
+	if (!alloc_more_mem_on_socket(heap, size, socket, flags, align, bound,
+			contig)) {
 		ret = heap_alloc(heap, type, size, flags, align, bound, contig);
 
 		/* this should have succeeded */
@@ -424,14 +526,40 @@ malloc_heap_alloc(const char *type, size_t size, int socket_arg,
 	return NULL;
 }
 
+/* this function is exposed in malloc_mp.h */
+int
+malloc_heap_free_pages(void *aligned_start, size_t aligned_len)
+{
+	int n_pages, page_idx, max_page_idx;
+	struct rte_memseg_list *msl;
+
+	msl = rte_mem_virt2memseg_list(aligned_start);
+	if (msl == NULL)
+		return -1;
+
+	n_pages = aligned_len / msl->hugepage_sz;
+	page_idx = RTE_PTR_DIFF(aligned_start, msl->base_va) /
+			msl->hugepage_sz;
+	max_page_idx = page_idx + n_pages;
+
+	for (; page_idx < max_page_idx; page_idx++) {
+		struct rte_memseg *ms;
+
+		ms = rte_fbarray_get(&msl->memseg_arr, page_idx);
+		eal_memalloc_free_page(ms);
+	}
+	return 0;
+}
+
 int
 malloc_heap_free(struct malloc_elem *elem)
 {
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
 	struct malloc_heap *heap;
 	void *start, *aligned_start, *end, *aligned_end;
 	size_t len, aligned_len;
 	struct rte_memseg_list *msl;
-	int n_pages, page_idx, max_page_idx, ret;
+	int n_pages, ret;
 
 	if (!malloc_elem_cookies_ok(elem) || elem->state != ELEM_BUSY)
 		return -1;
@@ -463,30 +591,60 @@ malloc_heap_free(struct malloc_elem *elem)
 	aligned_end = RTE_PTR_ALIGN_FLOOR(end, msl->hugepage_sz);
 
 	aligned_len = RTE_PTR_DIFF(aligned_end, aligned_start);
+	n_pages = aligned_len / msl->hugepage_sz;
 
 	/* can't free anything */
-	if (aligned_len < msl->hugepage_sz)
+	if (n_pages == 0)
 		goto free_unlock;
 
+	rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
+
+	/*
+	 * we allow secondary processes to clear the heap of this allocated
+	 * memory because it is safe to do so, as even if notifications about
+	 * unmapped pages don't make it to other processes, heap is shared
+	 * across all processes, and will become empty of this memory anyway,
+	 * and nothing can allocate it back unless primary process will be able
+	 * to deliver allocation message to every single running process.
+	 */
+
 	malloc_elem_free_list_remove(elem);
 
 	malloc_elem_hide_region(elem, (void *) aligned_start, aligned_len);
 
-	/* we don't really care if we fail to deallocate memory */
-	n_pages = aligned_len / msl->hugepage_sz;
-	page_idx = RTE_PTR_DIFF(aligned_start, msl->base_va) / msl->hugepage_sz;
-	max_page_idx = page_idx + n_pages;
+	heap->total_size -= n_pages * msl->hugepage_sz;
 
-	for (; page_idx < max_page_idx; page_idx++) {
-		struct rte_memseg *ms;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* don't care if any of this fails */
+		malloc_heap_free_pages(aligned_start, aligned_len);
 
-		ms = rte_fbarray_get(&msl->memseg_arr, page_idx);
-		eal_memalloc_free_page(ms);
-		heap->total_size -= msl->hugepage_sz;
+		request_sync();
+	} else {
+		struct malloc_mp_req req;
+
+		req.t = REQ_TYPE_FREE;
+		req.free_req.addr = aligned_start;
+		req.free_req.len = aligned_len;
+
+		/*
+		 * we request primary to deallocate pages, but we don't do it
+		 * in this thread. instead, we notify primary that we would like
+		 * to deallocate pages, and this process will receive another
+		 * request (in parallel) that will do it for us on another
+		 * thread.
+		 *
+		 * we also don't really care if this succeeds - the data is
+		 * already removed from the heap, so it is, for all intents and
+		 * purposes, hidden from the rest of DPDK even if some other
+		 * process (including this one) may have these pages mapped.
+		 */
+		request_to_primary(&req);
 	}
 
 	RTE_LOG(DEBUG, EAL, "Heap on socket %d was shrunk by %zdMB\n",
 		msl->socket_id, aligned_len >> 20ULL);
+
+	rte_rwlock_write_unlock(&mcfg->memory_hotplug_lock);
 free_unlock:
 	rte_spinlock_unlock(&(heap->lock));
 	return ret;
@@ -579,6 +737,11 @@ rte_eal_malloc_heap_init(void)
 	if (mcfg == NULL)
 		return -1;
 
+	if (register_mp_requests()) {
+		RTE_LOG(ERR, EAL, "Couldn't register malloc multiprocess actions\n");
+		return -1;
+	}
+
 	/* secondary processes don't need to initialize heap */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
 		return 0;
@@ -604,6 +767,7 @@ rte_eal_malloc_heap_init(void)
 						rte_fbarray_get(arr, ms_idx);
 				malloc_heap_add_memory(heap, msl,
 						ms->addr, ms->len);
+				heap->total_size += ms->len;
 				ms_idx++;
 				RTE_LOG(DEBUG, EAL, "Heap on socket %d was expanded by %zdMB\n",
 					msl->socket_id, ms->len >> 20ULL);
@@ -630,6 +794,8 @@ rte_eal_malloc_heap_init(void)
 			 */
 			malloc_heap_add_memory(heap, msl, start_seg->addr, len);
 
+			heap->total_size += len;
+
 			RTE_LOG(DEBUG, EAL, "Heap on socket %d was expanded by %zdMB\n",
 				msl->socket_id, len >> 20ULL);
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
new file mode 100644
index 0000000..8052680
--- /dev/null
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -0,0 +1,723 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <sys/time.h>
+
+#include <rte_alarm.h>
+#include <rte_errno.h>
+
+#include "eal_memalloc.h"
+
+#include "malloc_elem.h"
+#include "malloc_mp.h"
+
+#define MP_ACTION_SYNC "mp_malloc_sync"
+/**< request sent by primary process to notify of changes in memory map */
+#define MP_ACTION_ROLLBACK "mp_malloc_rollback"
+/**< request sent by primary process to notify of changes in memory map. this is
+ * essentially a regular sync request, but we cannot send sync requests while
+ * another one is in progress, and we might have to - therefore, we do this as
+ * a separate callback.
+ */
+#define MP_ACTION_REQUEST "mp_malloc_request"
+/**< request sent by secondary process to ask for allocation/deallocation */
+#define MP_ACTION_RESPONSE "mp_malloc_response"
+/**< response sent to secondary process to indicate result of request */
+
+#define MP_TIMEOUT_S 5 /**< 5 seconds timeouts */
+
+/* when we're allocating, we need to store some state to ensure that we can
+ * roll back later
+ */
+struct primary_alloc_req_state {
+	struct malloc_heap *heap;
+	struct rte_memseg **ms;
+	int ms_len;
+	struct malloc_elem *elem;
+	void *map_addr;
+	size_t map_len;
+};
+
+enum req_state {
+	REQ_STATE_INACTIVE = 0,
+	REQ_STATE_ACTIVE,
+	REQ_STATE_COMPLETE
+};
+
+struct mp_request {
+	TAILQ_ENTRY(mp_request) next;
+	struct malloc_mp_req user_req; /**< contents of request */
+	pthread_cond_t cond; /**< variable we use to time out on this request */
+	enum req_state state; /**< indicate status of this request */
+	struct primary_alloc_req_state alloc_state;
+};
+
+/*
+ * We could've used just a single request, but it may be possible for
+ * secondaries to timeout earlier than the primary, and send a new request while
+ * primary is still expecting replies to the old one. Therefore, each new
+ * request will get assigned a new ID, which is how we will distinguish between
+ * expected and unexpected messages.
+ */
+TAILQ_HEAD(mp_request_list, mp_request);
+static struct {
+	struct mp_request_list list;
+	pthread_mutex_t lock;
+} mp_request_list = {
+	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
+	.lock = PTHREAD_MUTEX_INITIALIZER
+};
+
+/**
+ * General workflow is the following:
+ *
+ * Allocation:
+ * S: send request to primary
+ * P: attempt to allocate memory
+ *    if failed, sendmsg failure
+ *    if success, send sync request
+ * S: if received msg of failure, quit
+ *    if received sync request, synchronize memory map and reply with result
+ * P: if received sync request result
+ *    if success, sendmsg success
+ *    if failure, roll back allocation and send a rollback request
+ * S: if received msg of success, quit
+ *    if received rollback request, synchronize memory map and reply with result
+ * P: if received sync request result
+ *    sendmsg sync request result
+ * S: if received msg, quit
+ *
+ * Aside from timeouts, there are three points where we can quit:
+ *  - if allocation failed straight away
+ *  - if allocation and sync request succeeded
+ *  - if allocation succeeded, sync request failed, allocation rolled back and
+ *    rollback request received (irrespective of whether it succeeded or failed)
+ *
+ * Deallocation:
+ * S: send request to primary
+ * P: attempt to deallocate memory
+ *    if failed, sendmsg failure
+ *    if success, send sync request
+ * S: if received msg of failure, quit
+ *    if received sync request, synchronize memory map and reply with result
+ * P: if received sync request result
+ *    sendmsg sync request result
+ * S: if received msg, quit
+ *
+ * There is no "rollback" from deallocation, as it's safe to have some memory
+ * mapped in some processes - it's absent from the heap, so it won't get used.
+ */
+
+static struct mp_request *
+find_request_by_id(uint64_t id)
+{
+	struct mp_request *req;
+	TAILQ_FOREACH(req, &mp_request_list.list, next) {
+		if (req->user_req.id == id)
+			break;
+	}
+	return req;
+}
+
+/* this ID is, like, totally guaranteed to be absolutely unique. pinky swear. */
+static uint64_t
+get_unique_id(void)
+{
+	uint64_t id;
+	do {
+		id = rte_rand();
+	} while (find_request_by_id(id) != NULL);
+	return id;
+}
+
+/* secondary will respond to sync requests thusly */
+static int
+handle_sync(const struct rte_mp_msg *msg, const void *peer)
+{
+	struct rte_mp_msg reply = {0};
+	const struct malloc_mp_req *req =
+			(const struct malloc_mp_req *)msg->param;
+	struct malloc_mp_req *resp =
+			(struct malloc_mp_req *)reply.param;
+	int ret;
+
+	if (req->t != REQ_TYPE_SYNC) {
+		RTE_LOG(ERR, EAL, "Unexpected request from primary\n");
+		return -1;
+	}
+
+	reply.num_fds = 0;
+	snprintf(reply.name, sizeof(reply.name), "%s", msg->name);
+	reply.len_param = sizeof(*resp);
+
+	ret = eal_memalloc_sync_with_primary();
+
+	resp->t = REQ_TYPE_SYNC;
+	resp->id = req->id;
+	resp->result = ret == 0 ? REQ_RESULT_SUCCESS : REQ_RESULT_FAIL;
+
+	rte_mp_reply(&reply, peer);
+
+	return 0;
+}
+
+static int
+handle_alloc_request(const struct malloc_mp_req *m,
+		struct mp_request *req)
+{
+	const struct malloc_req_alloc *ar = &m->alloc_req;
+	struct malloc_heap *heap;
+	struct malloc_elem *elem;
+	struct rte_memseg **ms;
+	size_t map_len;
+	int n_pages;
+
+	map_len = RTE_ALIGN_CEIL(ar->align + ar->elt_size +
+			MALLOC_ELEM_TRAILER_LEN, ar->page_sz);
+	n_pages = map_len / ar->page_sz;
+
+	heap = ar->heap;
+
+	/* we can't know in advance how many pages we'll need, so we malloc */
+	ms = malloc(sizeof(*ms) * n_pages);
+
+	if (ms == NULL) {
+		RTE_LOG(ERR, EAL, "Couldn't allocate memory for request state\n");
+		goto fail;
+	}
+
+	elem = alloc_pages_on_heap(heap, ar->page_sz, ar->elt_size, ar->socket,
+			ar->flags, ar->align, ar->bound, ar->contig, ms,
+			n_pages);
+
+	if (elem == NULL)
+		goto fail;
+
+	/* we have succeeded in allocating memory, but we still need to sync
+	 * with other processes. however, since DPDK IPC is single-threaded, we
+	 * send an asynchronous request and exit this callback.
+	 */
+
+	req->alloc_state.ms = ms;
+	req->alloc_state.ms_len = n_pages;
+	req->alloc_state.map_addr = ms[0]->addr;
+	req->alloc_state.map_len = map_len;
+	req->alloc_state.elem = elem;
+	req->alloc_state.heap = heap;
+
+	return 0;
+fail:
+	free(ms);
+	return -1;
+}
+
+/* first stage of primary handling requests from secondary */
+static int
+handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
+{
+	const struct malloc_mp_req *m =
+			(const struct malloc_mp_req *)msg->param;
+	struct mp_request *entry;
+	int ret;
+
+	/* lock access to request */
+	pthread_mutex_lock(&mp_request_list.lock);
+
+	/* make sure it's not a dupe */
+	entry = find_request_by_id(m->id);
+	if (entry != NULL) {
+		RTE_LOG(ERR, EAL, "Duplicate request id\n");
+		goto fail;
+	}
+
+	entry = malloc(sizeof(*entry));
+	if (entry == NULL) {
+		RTE_LOG(ERR, EAL, "Unable to allocate memory for request\n");
+		goto fail;
+	}
+
+	/* erase all data */
+	memset(entry, 0, sizeof(*entry));
+
+	if (m->t == REQ_TYPE_ALLOC) {
+		ret = handle_alloc_request(m, entry);
+	} else if (m->t == REQ_TYPE_FREE) {
+		ret = malloc_heap_free_pages(m->free_req.addr,
+				m->free_req.len);
+	} else {
+		RTE_LOG(ERR, EAL, "Unexpected request from secondary\n");
+		goto fail;
+	}
+
+	if (ret != 0) {
+		struct rte_mp_msg resp_msg;
+		struct malloc_mp_req *resp =
+				(struct malloc_mp_req *)resp_msg.param;
+
+		/* send failure message straight away */
+		resp_msg.num_fds = 0;
+		resp_msg.len_param = sizeof(*resp);
+		snprintf(resp_msg.name, sizeof(resp_msg.name), "%s",
+				MP_ACTION_RESPONSE);
+
+		resp->t = m->t;
+		resp->result = REQ_RESULT_FAIL;
+		resp->id = m->id;
+
+		if (rte_mp_sendmsg(&resp_msg)) {
+			RTE_LOG(ERR, EAL, "Couldn't send response\n");
+			goto fail;
+		}
+		/* we did not modify the request */
+		free(entry);
+	} else {
+		struct rte_mp_msg sr_msg = {0};
+		struct malloc_mp_req *sr =
+				(struct malloc_mp_req *)sr_msg.param;
+		struct timespec ts;
+
+		/* we can do something, so send sync request asynchronously */
+		sr_msg.num_fds = 0;
+		sr_msg.len_param = sizeof(*sr);
+		snprintf(sr_msg.name, sizeof(sr_msg.name), "%s",
+				MP_ACTION_SYNC);
+
+		ts.tv_nsec = 0;
+		ts.tv_sec = MP_TIMEOUT_S;
+
+		/* sync requests carry no data */
+		sr->t = REQ_TYPE_SYNC;
+		sr->id = m->id;
+
+		/* there may be stray timeout still waiting */
+		do {
+			ret = rte_mp_request_async(&sr_msg, &ts);
+		} while (ret != 0 && rte_errno == EEXIST);
+		if (ret != 0) {
+			RTE_LOG(ERR, EAL, "Couldn't send sync request\n");
+			if (m->t == REQ_TYPE_ALLOC)
+				free(entry->alloc_state.ms);
+			goto fail;
+		}
+
+		/* mark request as in progress */
+		memcpy(&entry->user_req, m, sizeof(*m));
+		entry->state = REQ_STATE_ACTIVE;
+
+		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
+	}
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return 0;
+fail:
+	pthread_mutex_unlock(&mp_request_list.lock);
+	free(entry);
+	return -1;
+}
+
+/* callback for asynchronous sync requests for primary. this will either do a
+ * sendmsg with results, or trigger rollback request.
+ */
+static int
+handle_sync_response(const struct rte_mp_msg *request,
+		const struct rte_mp_reply *reply)
+{
+	enum malloc_req_result result;
+	struct mp_request *entry;
+	const struct malloc_mp_req *mpreq =
+			(const struct malloc_mp_req *)request->param;
+	int i;
+
+	/* lock the request */
+	pthread_mutex_lock(&mp_request_list.lock);
+
+	entry = find_request_by_id(mpreq->id);
+	if (entry == NULL) {
+		RTE_LOG(ERR, EAL, "Wrong request ID\n");
+		goto fail;
+	}
+
+	result = REQ_RESULT_SUCCESS;
+
+	if (reply->nb_received != reply->nb_sent)
+		result = REQ_RESULT_FAIL;
+
+	for (i = 0; i < reply->nb_received; i++) {
+		struct malloc_mp_req *resp =
+				(struct malloc_mp_req *)reply->msgs[i].param;
+
+		if (resp->t != REQ_TYPE_SYNC) {
+			RTE_LOG(ERR, EAL, "Unexpected response to sync request\n");
+			result = REQ_RESULT_FAIL;
+			break;
+		}
+		if (resp->id != entry->user_req.id) {
+			RTE_LOG(ERR, EAL, "Response to wrong sync request\n");
+			result = REQ_RESULT_FAIL;
+			break;
+		}
+		if (resp->result == REQ_RESULT_FAIL) {
+			result = REQ_RESULT_FAIL;
+			break;
+		}
+	}
+
+	if (entry->user_req.t == REQ_TYPE_FREE) {
+		struct rte_mp_msg msg = {0};
+		struct malloc_mp_req *resp = (struct malloc_mp_req *)msg.param;
+
+		/* this is a free request, just sendmsg result */
+		resp->t = REQ_TYPE_FREE;
+		resp->result = result;
+		resp->id = entry->user_req.id;
+		msg.num_fds = 0;
+		msg.len_param = sizeof(*resp);
+		snprintf(msg.name, sizeof(msg.name), "%s", MP_ACTION_RESPONSE);
+
+		if (rte_mp_sendmsg(&msg))
+			RTE_LOG(ERR, EAL, "Could not send message to secondary process\n");
+
+		TAILQ_REMOVE(&mp_request_list.list, entry, next);
+		free(entry);
+	} else if (entry->user_req.t == REQ_TYPE_ALLOC &&
+			result == REQ_RESULT_SUCCESS) {
+		struct malloc_heap *heap = entry->alloc_state.heap;
+		struct rte_mp_msg msg = {0};
+		struct malloc_mp_req *resp =
+				(struct malloc_mp_req *)msg.param;
+
+		heap->total_size += entry->alloc_state.map_len;
+
+		/* result is success, so just notify secondary about this */
+		resp->t = REQ_TYPE_ALLOC;
+		resp->result = result;
+		resp->id = entry->user_req.id;
+		msg.num_fds = 0;
+		msg.len_param = sizeof(*resp);
+		snprintf(msg.name, sizeof(msg.name), "%s", MP_ACTION_RESPONSE);
+
+		if (rte_mp_sendmsg(&msg))
+			RTE_LOG(ERR, EAL, "Could not send message to secondary process\n");
+
+		TAILQ_REMOVE(&mp_request_list.list, entry, next);
+		free(entry->alloc_state.ms);
+		free(entry);
+	} else if (entry->user_req.t == REQ_TYPE_ALLOC &&
+			result == REQ_RESULT_FAIL) {
+		struct rte_mp_msg rb_msg = {0};
+		struct malloc_mp_req *rb =
+				(struct malloc_mp_req *)rb_msg.param;
+		struct timespec ts;
+		struct primary_alloc_req_state *state =
+				&entry->alloc_state;
+		int ret;
+
+		/* we've failed to sync, so do a rollback */
+		rollback_expand_heap(state->ms, state->ms_len, state->elem,
+				state->map_addr, state->map_len);
+
+		/* send rollback request */
+		rb_msg.num_fds = 0;
+		rb_msg.len_param = sizeof(*rb);
+		snprintf(rb_msg.name, sizeof(rb_msg.name), "%s",
+				MP_ACTION_ROLLBACK);
+
+		ts.tv_nsec = 0;
+		ts.tv_sec = MP_TIMEOUT_S;
+
+		/* sync requests carry no data */
+		rb->t = REQ_TYPE_SYNC;
+		rb->id = entry->user_req.id;
+
+		/* there may be stray timeout still waiting */
+		do {
+			ret = rte_mp_request_async(&rb_msg, &ts);
+		} while (ret != 0 && rte_errno == EEXIST);
+		if (ret != 0) {
+			RTE_LOG(ERR, EAL, "Could not send rollback request to secondary process\n");
+
+			/* we couldn't send rollback request, but that's OK -
+			 * secondary will time out, and memory has been removed
+			 * from heap anyway.
+			 */
+			TAILQ_REMOVE(&mp_request_list.list, entry, next);
+			free(state->ms);
+			free(entry);
+			goto fail;
+		}
+	} else {
+		RTE_LOG(ERR, EAL, " to sync request of unknown type\n");
+		goto fail;
+	}
+
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return 0;
+fail:
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return -1;
+}
+
+static int
+handle_rollback_response(const struct rte_mp_msg *request,
+		const struct rte_mp_reply *reply __rte_unused)
+{
+	struct rte_mp_msg msg = {0};
+	struct malloc_mp_req *resp = (struct malloc_mp_req *)msg.param;
+	const struct malloc_mp_req *mpreq =
+			(const struct malloc_mp_req *)request->param;
+	struct mp_request *entry;
+
+	/* lock the request */
+	pthread_mutex_lock(&mp_request_list.lock);
+
+	entry = find_request_by_id(mpreq->id);
+	if (entry == NULL) {
+		RTE_LOG(ERR, EAL, "Wrong request ID\n");
+		goto fail;
+	}
+
+	if (entry->user_req.t != REQ_TYPE_ALLOC) {
+		RTE_LOG(ERR, EAL, "Unexpected active request\n");
+		goto fail;
+	}
+
+	/* we don't care if rollback succeeded, request still failed */
+	resp->t = REQ_TYPE_ALLOC;
+	resp->result = REQ_RESULT_FAIL;
+	resp->id = mpreq->id;
+	msg.num_fds = 0;
+	msg.len_param = sizeof(*resp);
+	snprintf(msg.name, sizeof(msg.name), "%s", MP_ACTION_RESPONSE);
+
+	if (rte_mp_sendmsg(&msg))
+		RTE_LOG(ERR, EAL, "Could not send message to secondary process\n");
+
+	/* clean up */
+	TAILQ_REMOVE(&mp_request_list.list, entry, next);
+	free(entry->alloc_state.ms);
+	free(entry);
+
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return 0;
+fail:
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return -1;
+}
+
+/* final stage of the request from secondary */
+static int
+handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
+{
+	const struct malloc_mp_req *m =
+			(const struct malloc_mp_req *)msg->param;
+	struct mp_request *entry;
+
+	pthread_mutex_lock(&mp_request_list.lock);
+
+	entry = find_request_by_id(m->id);
+	if (entry != NULL) {
+		/* update request status */
+		entry->user_req.result = m->result;
+
+		entry->state = REQ_STATE_COMPLETE;
+
+		/* trigger thread wakeup */
+		pthread_cond_signal(&entry->cond);
+	}
+
+	pthread_mutex_unlock(&mp_request_list.lock);
+
+	return 0;
+}
+
+/* synchronously request memory map sync, this is only called whenever primary
+ * process initiates the allocation.
+ */
+int
+request_sync(void)
+{
+	struct rte_mp_msg msg = {0};
+	struct rte_mp_reply reply = {0};
+	struct malloc_mp_req *req = (struct malloc_mp_req *)msg.param;
+	struct timespec ts;
+	int i, ret;
+
+	/* no need to create tailq entries as this is entirely synchronous */
+
+	msg.num_fds = 0;
+	msg.len_param = sizeof(*req);
+	snprintf(msg.name, sizeof(msg.name), "%s", MP_ACTION_SYNC);
+
+	/* sync request carries no data */
+	req->t = REQ_TYPE_SYNC;
+	req->id = get_unique_id();
+
+	ts.tv_nsec = 0;
+	ts.tv_sec = MP_TIMEOUT_S;
+
+	/* there may be stray timeout still waiting */
+	do {
+		ret = rte_mp_request(&msg, &reply, &ts);
+	} while (ret != 0 && rte_errno == EEXIST);
+	if (ret != 0) {
+		RTE_LOG(ERR, EAL, "Could not send sync request to secondary process\n");
+		ret = -1;
+		goto out;
+	}
+
+	if (reply.nb_received != reply.nb_sent) {
+		RTE_LOG(ERR, EAL, "Not all secondaries have responded\n");
+		ret = -1;
+		goto out;
+	}
+
+	for (i = 0; i < reply.nb_received; i++) {
+		struct malloc_mp_req *resp =
+				(struct malloc_mp_req *)reply.msgs[i].param;
+		if (resp->t != REQ_TYPE_SYNC) {
+			RTE_LOG(ERR, EAL, "Unexpected response from secondary\n");
+			ret = -1;
+			goto out;
+		}
+		if (resp->id != req->id) {
+			RTE_LOG(ERR, EAL, "Wrong request ID\n");
+			ret = -1;
+			goto out;
+		}
+		if (resp->result != REQ_RESULT_SUCCESS) {
+			RTE_LOG(ERR, EAL, "Secondary process failed to synchronize\n");
+			ret = -1;
+			goto out;
+		}
+	}
+
+	ret = 0;
+out:
+	free(reply.msgs);
+	return ret;
+}
+
+/* this is a synchronous wrapper around a bunch of asynchronous requests to
+ * primary process. this will initiate a request and wait until responses come.
+ */
+int
+request_to_primary(struct malloc_mp_req *user_req)
+{
+	struct rte_mp_msg msg = {0};
+	struct malloc_mp_req *msg_req = (struct malloc_mp_req *)msg.param;
+	struct mp_request *entry;
+	struct timespec ts = {0};
+	struct timeval now;
+	int ret;
+
+	pthread_mutex_lock(&mp_request_list.lock);
+
+	entry = malloc(sizeof(*entry));
+	if (entry == NULL) {
+		RTE_LOG(ERR, EAL, "Cannot allocate memory for request\n");
+		goto fail;
+	}
+
+	memset(entry, 0, sizeof(*entry));
+
+	if (gettimeofday(&now, NULL) < 0) {
+		RTE_LOG(ERR, EAL, "Cannot get current time\n");
+		goto fail;
+	}
+
+	ts.tv_nsec = (now.tv_usec * 1000) % 1000000000;
+	ts.tv_sec = now.tv_sec + MP_TIMEOUT_S +
+			(now.tv_usec * 1000) / 1000000000;
+
+	/* initialize the request */
+	pthread_cond_init(&entry->cond, NULL);
+
+	msg.num_fds = 0;
+	msg.len_param = sizeof(*msg_req);
+	snprintf(msg.name, sizeof(msg.name), "%s", MP_ACTION_REQUEST);
+
+	/* (attempt to) get a unique id */
+	user_req->id = get_unique_id();
+
+	/* copy contents of user request into the message */
+	memcpy(msg_req, user_req, sizeof(*msg_req));
+
+	if (rte_mp_sendmsg(&msg)) {
+		RTE_LOG(ERR, EAL, "Cannot send message to primary\n");
+		goto fail;
+	}
+
+	/* copy contents of user request into active request */
+	memcpy(&entry->user_req, user_req, sizeof(*user_req));
+
+	/* mark request as in progress */
+	entry->state = REQ_STATE_ACTIVE;
+
+	TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
+
+	/* finally, wait on timeout */
+	do {
+		ret = pthread_cond_timedwait(&entry->cond,
+				&mp_request_list.lock, &ts);
+	} while (ret != 0 && ret != ETIMEDOUT);
+
+	if (entry->state != REQ_STATE_COMPLETE) {
+		RTE_LOG(ERR, EAL, "Request timed out\n");
+		ret = -1;
+	} else {
+		ret = 0;
+		user_req->result = entry->user_req.result;
+	}
+	TAILQ_REMOVE(&mp_request_list.list, entry, next);
+	free(entry);
+
+	pthread_mutex_unlock(&mp_request_list.lock);
+	return ret;
+fail:
+	pthread_mutex_unlock(&mp_request_list.lock);
+	free(entry);
+	return -1;
+}
+
+int
+register_mp_requests(void)
+{
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		if (rte_mp_action_register(MP_ACTION_REQUEST, handle_request)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_REQUEST);
+			return -1;
+		}
+		if (rte_mp_async_reply_register(MP_ACTION_SYNC,
+				handle_sync_response)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_SYNC);
+			return -1;
+		}
+		if (rte_mp_async_reply_register(MP_ACTION_ROLLBACK,
+				handle_rollback_response)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_ROLLBACK);
+			return -1;
+		}
+	} else {
+		if (rte_mp_action_register(MP_ACTION_SYNC, handle_sync)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_SYNC);
+			return -1;
+		}
+		if (rte_mp_action_register(MP_ACTION_ROLLBACK, handle_sync)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_SYNC);
+			return -1;
+		}
+		if (rte_mp_action_register(MP_ACTION_RESPONSE,
+				handle_response)) {
+			RTE_LOG(ERR, EAL, "Couldn't register '%s' action\n",
+				MP_ACTION_RESPONSE);
+			return -1;
+		}
+	}
+	return 0;
+}
diff --git a/lib/librte_eal/common/malloc_mp.h b/lib/librte_eal/common/malloc_mp.h
new file mode 100644
index 0000000..9c79d31
--- /dev/null
+++ b/lib/librte_eal/common/malloc_mp.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef MALLOC_MP_H
+#define MALLOC_MP_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_random.h>
+#include <rte_spinlock.h>
+#include <rte_tailq.h>
+
+/* forward declarations */
+struct malloc_heap;
+struct rte_memseg;
+
+/* multiprocess synchronization structures for malloc */
+enum malloc_req_type {
+	REQ_TYPE_ALLOC,     /**< ask primary to allocate */
+	REQ_TYPE_FREE,      /**< ask primary to free */
+	REQ_TYPE_SYNC       /**< ask secondary to synchronize its memory map */
+};
+
+enum malloc_req_result {
+	REQ_RESULT_SUCCESS,
+	REQ_RESULT_FAIL
+};
+
+struct malloc_req_alloc {
+	struct malloc_heap *heap;
+	uint64_t page_sz;
+	size_t elt_size;
+	int socket;
+	unsigned int flags;
+	size_t align;
+	size_t bound;
+	bool contig;
+};
+
+struct malloc_req_free {
+	RTE_STD_C11
+	union {
+		void *addr;
+		uint64_t addr_64;
+	};
+	uint64_t len;
+};
+
+struct malloc_mp_req {
+	enum malloc_req_type t;
+	RTE_STD_C11
+	union {
+		struct malloc_req_alloc alloc_req;
+		struct malloc_req_free free_req;
+	};
+	uint64_t id; /**< not to be populated by caller */
+	enum malloc_req_result result;
+};
+
+int
+register_mp_requests(void);
+
+int
+request_to_primary(struct malloc_mp_req *req);
+
+/* synchronous memory map sync request */
+int
+request_sync(void);
+
+/* functions from malloc_heap exposed here */
+int
+malloc_heap_free_pages(void *aligned_start, size_t aligned_len);
+
+struct malloc_elem *
+alloc_pages_on_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
+		int socket, unsigned int flags, size_t align, size_t bound,
+		bool contig, struct rte_memseg **ms, int n_pages);
+
+void
+rollback_expand_heap(struct rte_memseg **ms, int n_pages,
+		struct malloc_elem *elem, void *map_addr, size_t map_len);
+
+#endif // MALLOC_MP_H
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index a1ada24..8a3dcfe 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -27,6 +27,7 @@ common_sources = files(
 	'eal_common_timer.c',
 	'malloc_elem.c',
 	'malloc_heap.c',
+	'malloc_mp.c',
 	'rte_keepalive.c',
 	'rte_malloc.c',
 	'rte_reciprocal.c',
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 5380ba8..542bf7e 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -67,6 +67,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_fbarray.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_malloc.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_elem.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_heap.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_mp.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_keepalive.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_service.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_reciprocal.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 7a0d742..4bf8828 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -314,6 +314,8 @@ rte_config_init(void)
 	case RTE_PROC_INVALID:
 		rte_panic("Invalid process type\n");
 	}
+	/* disallow memory hotplug while init is active */
+	rte_rwlock_read_lock(&rte_config.mem_config->memory_hotplug_lock);
 }
 
 /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */
@@ -676,6 +678,7 @@ rte_eal_mcfg_complete(void)
 		rte_config.mem_config->magic = RTE_MAGIC;
 
 	internal_config.init_complete = 1;
+	rte_rwlock_read_unlock(&rte_config.mem_config->memory_hotplug_lock);
 }
 
 /*
@@ -842,14 +845,14 @@ rte_eal_init(int argc, char **argv)
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic32_clear(&run_once);
-		return -1;
+		goto fail;
 	}
 
 	if (rte_mp_channel_init() < 0) {
 		rte_eal_init_alert("failed to init mp channel\n");
 		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
 			rte_errno = EFAULT;
-			return -1;
+			goto fail;
 		}
 	}
 
@@ -858,7 +861,7 @@ rte_eal_init(int argc, char **argv)
 		rte_eal_init_alert("Cannot init VFIO\n");
 		rte_errno = EAGAIN;
 		rte_atomic32_clear(&run_once);
-		return -1;
+		goto fail;
 	}
 #endif
 	/* memzone_init maps rte_fbarrays, which has to be done before hugepage
@@ -868,13 +871,13 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_memzone_init() < 0) {
 		rte_eal_init_alert("Cannot init memzone\n");
 		rte_errno = ENODEV;
-		return -1;
+		goto fail;
 	}
 
 	if (rte_eal_memory_init() < 0) {
 		rte_eal_init_alert("Cannot init memory\n");
 		rte_errno = ENOMEM;
-		return -1;
+		goto fail;
 	}
 
 	/* the directories are locked during eal_hugepage_info_init */
@@ -883,25 +886,25 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_malloc_heap_init() < 0) {
 		rte_eal_init_alert("Cannot init malloc heap\n");
 		rte_errno = ENODEV;
-		return -1;
+		goto fail;
 	}
 
 	if (rte_eal_tailqs_init() < 0) {
 		rte_eal_init_alert("Cannot init tail queues for objects\n");
 		rte_errno = EFAULT;
-		return -1;
+		goto fail;
 	}
 
 	if (rte_eal_alarm_init() < 0) {
 		rte_eal_init_alert("Cannot init interrupt-handling thread\n");
 		/* rte_eal_alarm_init sets rte_errno on failure. */
-		return -1;
+		goto fail;
 	}
 
 	if (rte_eal_timer_init() < 0) {
 		rte_eal_init_alert("Cannot init HPET or TSC timers\n");
 		rte_errno = ENOTSUP;
-		return -1;
+		goto fail;
 	}
 
 	eal_check_mem_on_local_socket();
@@ -916,7 +919,7 @@ rte_eal_init(int argc, char **argv)
 
 	if (rte_eal_intr_init() < 0) {
 		rte_eal_init_alert("Cannot init interrupt-handling thread\n");
-		return -1;
+		goto fail;
 	}
 
 	RTE_LCORE_FOREACH_SLAVE(i) {
@@ -925,18 +928,24 @@ rte_eal_init(int argc, char **argv)
 		 * create communication pipes between master thread
 		 * and children
 		 */
-		if (pipe(lcore_config[i].pipe_master2slave) < 0)
-			rte_panic("Cannot create pipe\n");
-		if (pipe(lcore_config[i].pipe_slave2master) < 0)
-			rte_panic("Cannot create pipe\n");
+		if (pipe(lcore_config[i].pipe_master2slave) < 0) {
+			rte_eal_init_alert("Cannot create pipe\n");
+			goto fail;
+		}
+		if (pipe(lcore_config[i].pipe_slave2master) < 0) {
+			rte_eal_init_alert("Cannot create pipe\n");
+			goto fail;
+		}
 
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
 		ret = pthread_create(&lcore_config[i].thread_id, NULL,
 				     eal_thread_loop, NULL);
-		if (ret != 0)
-			rte_panic("Cannot create thread\n");
+		if (ret != 0) {
+			rte_eal_init_alert("Cannot create thread\n");
+			goto fail;
+		}
 
 		/* Set thread_name for aid in debugging. */
 		snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN,
@@ -960,14 +969,14 @@ rte_eal_init(int argc, char **argv)
 	if (ret) {
 		rte_eal_init_alert("rte_service_init() failed\n");
 		rte_errno = ENOEXEC;
-		return -1;
+		goto fail;
 	}
 
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe()) {
 		rte_eal_init_alert("Cannot probe devices\n");
 		rte_errno = ENOTSUP;
-		return -1;
+		goto fail;
 	}
 
 	/* initialize default service/lcore mappings and start running. Ignore
@@ -976,12 +985,15 @@ rte_eal_init(int argc, char **argv)
 	ret = rte_service_start_with_defaults();
 	if (ret < 0 && ret != -ENOTSUP) {
 		rte_errno = ENOEXEC;
-		return -1;
+		goto fail;
 	}
 
 	rte_eal_mcfg_complete();
 
 	return fctret;
+fail:
+	rte_rwlock_read_unlock(&rte_config.mem_config->memory_hotplug_lock);
+	return -1;
 }
 
 int __rte_experimental
-- 
2.7.4

  parent reply	other threads:[~2018-03-03 13:46 UTC|newest]

Thread overview: 471+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-03 13:45 [dpdk-dev] [PATCH 00/41] Memory Hotplug for DPDK Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 01/41] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 02/41] eal: move all locking to heap Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 03/41] eal: make malloc heap a doubly-linked list Anatoly Burakov
2018-03-19 17:33   ` Olivier Matz
2018-03-20  9:39     ` Burakov, Anatoly
2018-03-03 13:45 ` [dpdk-dev] [PATCH 04/41] eal: add function to dump malloc heap contents Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 05/41] test: add command " Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 06/41] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 07/41] eal: make malloc free list remove public Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 08/41] eal: make malloc free return resulting malloc element Anatoly Burakov
2018-03-19 17:34   ` Olivier Matz
2018-03-20  9:40     ` Burakov, Anatoly
2018-03-03 13:45 ` [dpdk-dev] [PATCH 09/41] eal: add rte_fbarray Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 10/41] eal: add "single file segments" command-line option Anatoly Burakov
2018-03-03 13:45 ` [dpdk-dev] [PATCH 11/41] eal: add "legacy memory" option Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 12/41] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 13/41] eal: replace memseg with memseg lists Anatoly Burakov
2018-03-19 17:39   ` Olivier Matz
2018-03-20  9:47     ` Burakov, Anatoly
2018-03-03 13:46 ` [dpdk-dev] [PATCH 14/41] eal: add support for mapping hugepages at runtime Anatoly Burakov
2018-03-19 17:42   ` Olivier Matz
2018-03-03 13:46 ` [dpdk-dev] [PATCH 15/41] eal: add support for unmapping pages " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 16/41] eal: make use of memory hotplug for init Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 17/41] eal: enable memory hotplug support in rte_malloc Anatoly Burakov
2018-03-19 17:46   ` Olivier Matz
2018-03-03 13:46 ` [dpdk-dev] [PATCH 18/41] test: fix malloc autotest to support memory hotplug Anatoly Burakov
2018-03-19 17:49   ` Olivier Matz
2018-03-03 13:46 ` [dpdk-dev] [PATCH 19/41] eal: add API to check if memory is contiguous Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 20/41] eal: add backend support for contiguous allocation Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 21/41] eal: enable reserving physically contiguous memzones Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 22/41] eal: replace memzone array with fbarray Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 23/41] mempool: add support for the new allocation methods Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 24/41] vfio: allow to map other memory regions Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 25/41] eal: map/unmap memory with VFIO when alloc/free pages Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 26/41] eal: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 27/41] eal: add multiprocess init with memory hotplug Anatoly Burakov
2018-03-03 13:46 ` Anatoly Burakov [this message]
2018-03-03 13:46 ` [dpdk-dev] [PATCH 29/41] eal: add support for callbacks on " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 30/41] eal: enable callbacks on malloc/free and mp sync Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 31/41] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-03-03 14:05   ` Andrew Rybchenko
2018-03-05  9:08     ` Burakov, Anatoly
2018-03-05  9:15       ` Andrew Rybchenko
2018-03-05 10:00         ` Burakov, Anatoly
2018-03-03 13:46 ` [dpdk-dev] [PATCH 32/41] crypto/qat: " Anatoly Burakov
2018-03-05 11:06   ` Trahe, Fiona
2018-03-03 13:46 ` [dpdk-dev] [PATCH 33/41] net/avf: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 34/41] net/bnx2x: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 35/41] net/cxgbe: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 36/41] net/ena: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 37/41] net/enic: " Anatoly Burakov
2018-03-05 19:45   ` John Daley (johndale)
2018-03-03 13:46 ` [dpdk-dev] [PATCH 38/41] net/i40e: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 39/41] net/qede: " Anatoly Burakov
2018-03-03 13:46 ` [dpdk-dev] [PATCH 40/41] net/virtio: " Anatoly Burakov
2018-03-03 16:52   ` Venkatesh Srinivas
2018-03-03 13:46 ` [dpdk-dev] [PATCH 41/41] net/vmxnet3: " Anatoly Burakov
2018-03-06 11:04 ` [dpdk-dev] [PATCH 00/41] Memory Hotplug for DPDK Burakov, Anatoly
2018-03-07 15:27 ` Nélio Laranjeiro
2018-03-07 16:05   ` Burakov, Anatoly
2018-03-08  9:37     ` Burakov, Anatoly
2018-03-08 10:53       ` Nélio Laranjeiro
2018-03-08 12:12         ` Burakov, Anatoly
2018-03-08 12:14           ` Bruce Richardson
2018-03-07 16:11   ` Burakov, Anatoly
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 " Anatoly Burakov
2018-03-08 10:18   ` Pavan Nikhilesh
2018-03-08 10:46     ` Burakov, Anatoly
2018-03-08 11:13       ` Pavan Nikhilesh
2018-03-08 13:36         ` Pavan Nikhilesh
2018-03-08 14:36           ` Burakov, Anatoly
2018-03-08 20:11             ` Burakov, Anatoly
2018-03-08 20:33               ` Burakov, Anatoly
2018-03-09  9:15                 ` Pavan Nikhilesh
2018-03-09 10:42                   ` Burakov, Anatoly
2018-03-12 15:58                     ` Nélio Laranjeiro
2018-03-13  5:17                     ` Shreyansh Jain
2018-03-15 14:01                       ` Shreyansh Jain
2018-03-21 13:45                         ` Shreyansh Jain
2018-03-21 14:48                           ` Burakov, Anatoly
2018-03-22  5:09                             ` Shreyansh Jain
2018-03-22  9:24                               ` Burakov, Anatoly
2018-03-19  8:58   ` Shreyansh Jain
2018-03-20 10:07     ` Burakov, Anatoly
2018-03-29 10:57       ` Shreyansh Jain
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 00/68] " Anatoly Burakov
2018-04-05 14:24     ` Shreyansh Jain
2018-04-05 14:12       ` Thomas Monjalon
2018-04-05 14:20         ` Hemant Agrawal
2018-04-06 12:01           ` Hemant Agrawal
2018-04-06 12:55             ` Burakov, Anatoly
2018-04-05 18:59     ` santosh
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 00/70] " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 " Anatoly Burakov
2018-04-09 18:35         ` gowrishankar muthukrishnan
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 " Anatoly Burakov
2018-04-11 18:07           ` Thomas Monjalon
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 01/70] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 02/70] malloc: move all locking to heap Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 03/70] malloc: make heap a doubly-linked list Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 04/70] malloc: add function to dump heap contents Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 05/70] test: add command to dump malloc " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 06/70] malloc: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 07/70] malloc: make elem_free_list_remove public Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 08/70] malloc: make free return resulting element Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 09/70] malloc: replace panics with error messages Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 10/70] malloc: add support for contiguous allocation Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 11/70] memzone: enable reserving IOVA-contiguous memzones Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 12/70] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 13/70] crypto/qat: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 14/70] net/avf: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 15/70] net/bnx2x: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 16/70] net/bnxt: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 17/70] net/cxgbe: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 18/70] net/ena: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 19/70] net/enic: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 20/70] net/i40e: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 21/70] net/qede: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 22/70] net/virtio: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 23/70] net/vmxnet3: " Anatoly Burakov
2018-04-11 12:29         ` [dpdk-dev] [PATCH v6 24/70] mempool: add support for the new allocation methods Anatoly Burakov
2018-04-11 14:35           ` Olivier Matz
2018-04-11 14:35           ` Olivier Matz
2018-04-11 14:43           ` Andrew Rybchenko
2018-04-11 15:03             ` Burakov, Anatoly
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 25/70] eal: add function to walk all memsegs Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 26/70] bus/fslmc: use memseg walk instead of iteration Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 27/70] bus/pci: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 28/70] net/mlx5: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 29/70] eal: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 30/70] mempool: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 31/70] test: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 32/70] vfio/type1: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 33/70] vfio/spapr: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 34/70] eal: add contig walk function Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 35/70] virtio: use memseg contig walk instead of iteration Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 36/70] eal: add iova2virt function Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 37/70] bus/dpaa: use iova2virt instead of memseg iteration Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 38/70] bus/fslmc: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 39/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 40/70] eal: add virt2memseg function Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 41/70] bus/fslmc: use virt2memseg instead of iteration Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 42/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 43/70] net/mlx4: " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 44/70] net/mlx5: " Anatoly Burakov
2018-04-17  2:48           ` Yongseok Koh
2018-04-17  9:03             ` Burakov, Anatoly
2018-04-17 18:08               ` Yongseok Koh
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 45/70] memzone: use walk instead of iteration for dumping Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 46/70] vfio: allow to map other memory regions Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 47/70] eal: add legacy memory option Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 48/70] eal: add shared indexed file-backed array Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 49/70] eal: replace memseg with memseg lists Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 50/70] eal: replace memzone array with fbarray Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 51/70] mem: add support for mapping hugepages at runtime Anatoly Burakov
2018-04-17  2:06           ` Yongseok Koh
2018-04-17  7:20             ` Thomas Monjalon
2018-04-17 18:13               ` Yongseok Koh
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 52/70] mem: add support for unmapping pages " Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 53/70] eal: add single file segments command-line option Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 54/70] mem: add internal API to check if memory is contiguous Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 55/70] mem: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 56/70] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 57/70] eal: make use of memory hotplug for init Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 58/70] eal: share hugepage info primary and secondary Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 59/70] eal: add secondary process init with memory hotplug Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 60/70] malloc: enable memory hotplug support Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 61/70] malloc: add support for multiprocess memory hotplug Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 62/70] malloc: add support for callbacks on memory events Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 63/70] malloc: enable callbacks on alloc/free and mp sync Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 64/70] vfio: enable support for mem event callbacks Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 65/70] bus/fslmc: move vfio DMA map into bus probe Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 66/70] bus/fslmc: enable support for mem event callbacks for vfio Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 67/70] eal: enable non-legacy memory mode Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 68/70] eal: add memory validator callback Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 69/70] malloc: enable validation before new page allocation Anatoly Burakov
2018-04-11 12:30         ` [dpdk-dev] [PATCH v6 70/70] mem: prevent preallocated pages from being freed Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 01/70] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 02/70] eal: move all locking to heap Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 03/70] eal: make malloc heap a doubly-linked list Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 04/70] eal: add function to dump malloc heap contents Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 05/70] test: add command " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 06/70] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 07/70] eal: make malloc free list remove public Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 08/70] eal: make malloc free return resulting malloc element Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 09/70] eal: replace panics with error messages in malloc Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 10/70] eal: add backend support for contiguous allocation Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 11/70] eal: enable reserving physically contiguous memzones Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 12/70] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 13/70] crypto/qat: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 14/70] net/avf: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 15/70] net/bnx2x: " Anatoly Burakov
2018-04-11  9:12         ` Thomas Monjalon
2018-04-11  9:18           ` Burakov, Anatoly
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 16/70] net/bnxt: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 17/70] net/cxgbe: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 18/70] net/ena: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 19/70] net/enic: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 20/70] net/i40e: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 21/70] net/qede: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 22/70] net/virtio: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 23/70] net/vmxnet3: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 24/70] mempool: add support for the new allocation methods Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 25/70] eal: add function to walk all memsegs Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 26/70] bus/fslmc: use memseg walk instead of iteration Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 27/70] bus/pci: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 28/70] net/mlx5: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 29/70] eal: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 30/70] mempool: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 31/70] test: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 32/70] vfio/type1: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 33/70] vfio/spapr: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 34/70] eal: add contig walk function Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 35/70] virtio: use memseg contig walk instead of iteration Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 36/70] eal: add iova2virt function Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 37/70] bus/dpaa: use iova2virt instead of memseg iteration Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 38/70] bus/fslmc: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 39/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 40/70] eal: add virt2memseg function Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 41/70] bus/fslmc: use virt2memseg instead of iteration Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 42/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 43/70] net/mlx4: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 44/70] net/mlx5: " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 45/70] eal: use memzone walk " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 46/70] vfio: allow to map other memory regions Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 47/70] eal: add "legacy memory" option Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 48/70] eal: add rte_fbarray Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 49/70] eal: replace memseg with memseg lists Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 50/70] eal: replace memzone array with fbarray Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 51/70] eal: add support for mapping hugepages at runtime Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 52/70] eal: add support for unmapping pages " Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 53/70] eal: add "single file segments" command-line option Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 54/70] eal: add API to check if memory is contiguous Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 55/70] eal: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-04-09 18:00       ` [dpdk-dev] [PATCH v5 56/70] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 57/70] eal: make use of memory hotplug for init Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 58/70] eal: share hugepage info primary and secondary Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 59/70] eal: add secondary process init with memory hotplug Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 60/70] eal: enable memory hotplug support in rte_malloc Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 61/70] eal: add support for multiprocess memory hotplug Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 62/70] eal: add support for callbacks on " Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 63/70] eal: enable callbacks on malloc/free and mp sync Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 64/70] vfio: enable support for mem event callbacks Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 65/70] bus/fslmc: move vfio DMA map into bus probe Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 66/70] bus/fslmc: enable support for mem event callbacks for vfio Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 67/70] eal: enable non-legacy memory mode Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 68/70] eal: add memory validator callback Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 69/70] eal: enable validation before new page allocation Anatoly Burakov
2018-04-09 18:01       ` [dpdk-dev] [PATCH v5 70/70] eal: prevent preallocated pages from being freed Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 01/70] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 02/70] eal: move all locking to heap Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 03/70] eal: make malloc heap a doubly-linked list Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 04/70] eal: add function to dump malloc heap contents Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 05/70] test: add command " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 06/70] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 07/70] eal: make malloc free list remove public Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 08/70] eal: make malloc free return resulting malloc element Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 09/70] eal: replace panics with error messages in malloc Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 10/70] eal: add backend support for contiguous allocation Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 11/70] eal: enable reserving physically contiguous memzones Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 12/70] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 13/70] crypto/qat: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 14/70] net/avf: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 15/70] net/bnx2x: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 16/70] net/bnxt: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 17/70] net/cxgbe: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 18/70] net/ena: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 19/70] net/enic: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 20/70] net/i40e: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 21/70] net/qede: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 22/70] net/virtio: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 23/70] net/vmxnet3: " Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 24/70] mempool: add support for the new allocation methods Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 25/70] eal: add function to walk all memsegs Anatoly Burakov
2018-04-08 20:17     ` [dpdk-dev] [PATCH v4 26/70] bus/fslmc: use memseg walk instead of iteration Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 27/70] bus/pci: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 28/70] net/mlx5: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 29/70] eal: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 30/70] mempool: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 31/70] test: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 32/70] vfio/type1: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 33/70] vfio/spapr: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 34/70] eal: add contig walk function Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 35/70] virtio: use memseg contig walk instead of iteration Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 36/70] eal: add iova2virt function Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 37/70] bus/dpaa: use iova2virt instead of memseg iteration Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 38/70] bus/fslmc: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 39/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 40/70] eal: add virt2memseg function Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 41/70] bus/fslmc: use virt2memseg instead of iteration Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 42/70] crypto/dpaa_sec: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 43/70] net/mlx4: " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 44/70] net/mlx5: " Anatoly Burakov
2018-04-09 10:26       ` gowrishankar muthukrishnan
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 45/70] eal: use memzone walk " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 46/70] vfio: allow to map other memory regions Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 47/70] eal: add "legacy memory" option Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 48/70] eal: add rte_fbarray Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 49/70] eal: replace memseg with memseg lists Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 50/70] eal: replace memzone array with fbarray Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 51/70] eal: add support for mapping hugepages at runtime Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 52/70] eal: add support for unmapping pages " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 53/70] eal: add "single file segments" command-line option Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 54/70] eal: add API to check if memory is contiguous Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 55/70] eal: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 56/70] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 57/70] eal: make use of memory hotplug for init Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 58/70] eal: share hugepage info primary and secondary Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 59/70] eal: add secondary process init with memory hotplug Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 60/70] eal: enable memory hotplug support in rte_malloc Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 61/70] eal: add support for multiprocess memory hotplug Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 62/70] eal: add support for callbacks on " Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 63/70] eal: enable callbacks on malloc/free and mp sync Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 64/70] vfio: enable support for mem event callbacks Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 65/70] bus/fslmc: move vfio DMA map into bus probe Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 66/70] bus/fslmc: enable support for mem event callbacks for vfio Anatoly Burakov
2018-04-09 10:01       ` Shreyansh Jain
2018-04-09 10:55         ` Burakov, Anatoly
2018-04-09 12:09           ` Shreyansh Jain
2018-04-09 12:35             ` Burakov, Anatoly
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 67/70] eal: enable non-legacy memory mode Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 68/70] eal: add memory validator callback Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 69/70] eal: enable validation before new page allocation Anatoly Burakov
2018-04-08 20:18     ` [dpdk-dev] [PATCH v4 70/70] eal: prevent preallocated pages from being freed Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 01/68] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 02/68] eal: move all locking to heap Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 03/68] eal: make malloc heap a doubly-linked list Anatoly Burakov
2018-04-03 23:32     ` Stephen Hemminger
2018-04-04  8:05       ` Burakov, Anatoly
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 04/68] eal: add function to dump malloc heap contents Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 05/68] test: add command " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 06/68] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 07/68] eal: make malloc free list remove public Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 08/68] eal: make malloc free return resulting malloc element Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 09/68] eal: replace panics with error messages in malloc Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 10/68] eal: add backend support for contiguous allocation Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 11/68] eal: enable reserving physically contiguous memzones Anatoly Burakov
2018-04-03 23:41     ` Stephen Hemminger
2018-04-04  8:01       ` Burakov, Anatoly
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 12/68] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 13/68] crypto/qat: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 14/68] net/avf: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 15/68] net/bnx2x: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 16/68] net/cxgbe: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 17/68] net/ena: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 18/68] net/enic: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 19/68] net/i40e: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 20/68] net/qede: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 21/68] net/virtio: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 22/68] net/vmxnet3: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 23/68] net/bnxt: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 24/68] mempool: add support for the new allocation methods Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 25/68] eal: add function to walk all memsegs Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 26/68] bus/fslmc: use memseg walk instead of iteration Anatoly Burakov
2018-04-05 14:06     ` Shreyansh Jain
2018-04-05 14:14     ` [dpdk-dev] [PATCH] bus/fslmc: support for hotplugging of memory Shreyansh Jain
2018-04-08 17:14       ` Burakov, Anatoly
2018-04-09  7:49         ` Shreyansh Jain
2018-04-09 15:49           ` Burakov, Anatoly
2018-04-09 16:06             ` Shreyansh Jain
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 27/68] bus/pci: use memseg walk instead of iteration Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 28/68] net/mlx5: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 29/68] eal: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 30/68] mempool: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 31/68] test: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 32/68] vfio/type1: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 33/68] vfio/spapr: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 34/68] eal: add contig walk function Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 35/68] virtio: use memseg contig walk instead of iteration Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 36/68] eal: add iova2virt function Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 37/68] bus/dpaa: use iova2virt instead of memseg iteration Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 38/68] bus/fslmc: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 39/68] crypto/dpaa_sec: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 40/68] eal: add virt2memseg function Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 41/68] bus/fslmc: use virt2memseg instead of iteration Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 42/68] net/mlx4: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 43/68] net/mlx5: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 44/68] crypto/dpaa_sec: " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 45/68] eal: use memzone walk " Anatoly Burakov
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 46/68] vfio: allow to map other memory regions Anatoly Burakov
2018-04-04 11:27     ` Burakov, Anatoly
2018-04-05 11:30     ` Burakov, Anatoly
2018-04-03 23:21   ` [dpdk-dev] [PATCH v3 47/68] eal: add "legacy memory" option Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 48/68] eal: add rte_fbarray Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 49/68] eal: replace memseg with memseg lists Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 50/68] eal: replace memzone array with fbarray Anatoly Burakov
2018-04-05 14:23     ` Shreyansh Jain
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 51/68] eal: add support for mapping hugepages at runtime Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 52/68] eal: add support for unmapping pages " Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 53/68] eal: add "single file segments" command-line option Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 54/68] eal: add API to check if memory is contiguous Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 55/68] eal: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 56/68] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 57/68] eal: make use of memory hotplug for init Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 58/68] eal: share hugepage info primary and secondary Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 59/68] eal: add secondary process init with memory hotplug Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 60/68] eal: enable memory hotplug support in rte_malloc Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 61/68] eal: add support for multiprocess memory hotplug Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 62/68] eal: add support for callbacks on " Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 63/68] eal: enable callbacks on malloc/free and mp sync Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 64/68] vfio: enable support for mem event callbacks Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 65/68] eal: enable non-legacy memory mode Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 66/68] eal: add memory validator callback Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 67/68] eal: enable validation before new page allocation Anatoly Burakov
2018-04-03 23:22   ` [dpdk-dev] [PATCH v3 68/68] eal: prevent preallocated pages from being freed Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 01/41] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 02/41] eal: move all locking to heap Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 03/41] eal: make malloc heap a doubly-linked list Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 04/41] eal: add function to dump malloc heap contents Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 05/41] test: add command " Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 06/41] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 07/41] eal: make malloc free list remove public Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 08/41] eal: make malloc free return resulting malloc element Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 09/41] eal: add rte_fbarray Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 10/41] eal: add "single file segments" command-line option Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 11/41] eal: add "legacy memory" option Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 12/41] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 13/41] eal: replace memseg with memseg lists Anatoly Burakov
2018-03-24  6:01   ` santosh
2018-03-24 11:08     ` Burakov, Anatoly
2018-03-24 12:23       ` santosh
2018-03-24 12:32         ` Burakov, Anatoly
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 14/41] eal: add support for mapping hugepages at runtime Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 15/41] eal: add support for unmapping pages " Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 16/41] eal: make use of memory hotplug for init Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 17/41] eal: enable memory hotplug support in rte_malloc Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 18/41] test: fix malloc autotest to support memory hotplug Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 19/41] eal: add API to check if memory is contiguous Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 20/41] eal: add backend support for contiguous allocation Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 21/41] eal: enable reserving physically contiguous memzones Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 22/41] eal: replace memzone array with fbarray Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 23/41] mempool: add support for the new allocation methods Anatoly Burakov
2018-03-19 17:11   ` Olivier Matz
2018-03-21  7:49     ` Andrew Rybchenko
2018-03-21  8:32       ` Olivier Matz
2018-03-20 11:35   ` Shreyansh Jain
2018-03-20 12:17     ` Burakov, Anatoly
2018-03-23 11:25     ` Burakov, Anatoly
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 24/41] vfio: allow to map other memory regions Anatoly Burakov
2018-03-30  9:42   ` Gowrishankar
2018-04-02 11:36   ` Gowrishankar
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 25/41] eal: map/unmap memory with VFIO when alloc/free pages Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 26/41] eal: prepare memseg lists for multiprocess sync Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 27/41] eal: add multiprocess init with memory hotplug Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 28/41] eal: add support for multiprocess " Anatoly Burakov
2018-03-23 15:44   ` Tan, Jianfeng
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 29/41] eal: add support for callbacks on " Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 30/41] eal: enable callbacks on malloc/free and mp sync Anatoly Burakov
2018-03-07 16:56 ` [dpdk-dev] [PATCH v2 31/41] ethdev: use contiguous allocation for DMA memory Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 32/41] crypto/qat: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 33/41] net/avf: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 34/41] net/bnx2x: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 35/41] net/cxgbe: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 36/41] net/ena: " Anatoly Burakov
2018-03-08  9:40   ` Michał Krawczyk
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 37/41] net/enic: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 38/41] net/i40e: " Anatoly Burakov
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 39/41] net/qede: " Anatoly Burakov
2018-03-07 22:55   ` Patil, Harish
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 40/41] net/virtio: " Anatoly Burakov
2018-03-28 11:58   ` Maxime Coquelin
2018-03-07 16:57 ` [dpdk-dev] [PATCH v2 41/41] net/vmxnet3: " Anatoly Burakov
2018-03-08 14:40 ` [dpdk-dev] [PATCH 00/41] Memory Hotplug for DPDK Burakov, Anatoly
2018-03-19 17:30 ` Olivier Matz
2018-03-20 10:27   ` Burakov, Anatoly
2018-03-20 12:42     ` Olivier Matz
2018-03-20 13:51       ` Burakov, Anatoly
2018-03-20 14:18         ` Olivier Matz
2018-03-20 14:46           ` Burakov, Anatoly
2018-03-21  9:09 ` gowrishankar muthukrishnan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=397814e6beaa81d1b3c598477b4984c59d9746c7.1520083504.git.anatoly.burakov@intel.com \
    --to=anatoly.burakov@intel.com \
    --cc=andras.kovacs@ericsson.com \
    --cc=benjamin.walker@intel.com \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=hemant.agrawal@nxp.com \
    --cc=jerin.jacob@caviumnetworks.com \
    --cc=jianfeng.tan@intel.com \
    --cc=keith.wiles@intel.com \
    --cc=konstantin.ananyev@intel.com \
    --cc=kuralamudhan.ramakrishnan@intel.com \
    --cc=laszlo.vadkeri@ericsson.com \
    --cc=louise.m.daly@intel.com \
    --cc=nelio.laranjeiro@6wind.com \
    --cc=olivier.matz@6wind.com \
    --cc=pepperjo@japf.ch \
    --cc=thomas@monjalon.net \
    --cc=yskoh@mellanox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).