|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v5 04/11] lib/uknetdev: Netbuf refcounting and releasing
Introduce reference counting and buffer releasing with Netbufs.
Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
---
lib/uknetdev/exportsyms.uk | 2 ++
lib/uknetdev/include/uk/netbuf.h | 73 ++++++++++++++++++++++++++++++++++++++++
lib/uknetdev/netbuf.c | 49 +++++++++++++++++++++++++++
3 files changed, 124 insertions(+)
diff --git a/lib/uknetdev/exportsyms.uk b/lib/uknetdev/exportsyms.uk
index 3153a5d..a05f502 100644
--- a/lib/uknetdev/exportsyms.uk
+++ b/lib/uknetdev/exportsyms.uk
@@ -2,6 +2,8 @@ uk_netbuf_init_indir
uk_netbuf_alloc_indir
uk_netbuf_alloc_buf
uk_netbuf_prepare_buf
+uk_netbuf_free_single
+uk_netbuf_free
uk_netbuf_disconnect
uk_netbuf_connect
uk_netbuf_append
diff --git a/lib/uknetdev/include/uk/netbuf.h b/lib/uknetdev/include/uk/netbuf.h
index c0cbb4a..3d884dd 100644
--- a/lib/uknetdev/include/uk/netbuf.h
+++ b/lib/uknetdev/include/uk/netbuf.h
@@ -329,6 +329,7 @@ struct uk_netbuf *uk_netbuf_prepare_buf(void *mem, size_t
size,
/**
* Connects two netbuf chains
+ * Note: The reference count of each buffer is not checked nor modified.
* @param headtail
* Last netbuf element of chain that should come first.
* It can also be just a single netbuf.
@@ -341,6 +342,7 @@ void uk_netbuf_connect(struct uk_netbuf *headtail,
/**
* Connects two netbuf chains
+ * Note: The reference count of each buffer is not checked nor modified.
* @param head
* Heading netbuf element of chain that should come first.
* It can also be just a single netbuf.
@@ -354,6 +356,7 @@ void uk_netbuf_append(struct uk_netbuf *head,
/**
* Disconnects a netbuf from its chain. The chain will remain
* without the removed element.
+ * Note: The reference count of each buffer is not checked nor modified.
* @param m
* uk_netbuf to be removed from its chain
* @returns
@@ -362,6 +365,76 @@ void uk_netbuf_append(struct uk_netbuf *head,
*/
struct uk_netbuf *uk_netbuf_disconnect(struct uk_netbuf *m);
+/**
+ * Increase reference count of a single netbuf (irrespective of a chain)
+ * @param m
+ * uk_netbuf to increase refcount of
+ * @returns
+ * Reference to m
+ */
+static inline struct uk_netbuf *uk_netbuf_ref_single(struct uk_netbuf *m)
+{
+ UK_ASSERT(m);
+
+ uk_refcount_acquire(&m->refcount);
+ return m;
+}
+
+/**
+ * Increase reference count of a netbuf including each successive netbuf
+ * element of a chain. Note, preceding chain elements are not visited.
+ * @param m
+ * head of the uk_netbuf chain to increase refcount of
+ * @returns
+ * Reference to m
+ */
+static inline struct uk_netbuf *uk_netbuf_ref(struct uk_netbuf *m)
+{
+ struct uk_netbuf *iter;
+
+ UK_ASSERT(m);
+
+ UK_NETBUF_CHAIN_FOREACH(iter, m)
+ uk_netbuf_ref_single(iter);
+
+ return m;
+}
+
+/**
+ * Returns the current reference count of a single netbuf
+ * @param m
+ * uk_netbuf to return the reference count of
+ */
+static inline uint32_t uk_netbuf_refcount_single_get(struct uk_netbuf *m)
+{
+ UK_ASSERT(m);
+
+ return uk_refcount_read(&m->refcount);
+}
+
+/**
+ * Decreases the reference count of each element of the chain.
+ * If a refcount becomes 0, the netbuf is disconnected from its chain,
+ * its destructor is called and the memory is free'd according to its
+ * allocation.
+ * @param m
+ * head of uk_netbuf chain to release
+ * @returns
+ * Reference to m
+ */
+void uk_netbuf_free(struct uk_netbuf *m);
+
+/**
+ * Decreases the reference count of a single netbuf. If refcount becomes 0,
+ * the netbuf is disconnected from its chain, its destructor is called and
+ * the memory is free'd according to its allocation.
+ * @param m
+ * uk_netbuf to release
+ * @returns
+ * Reference to m
+ */
+void uk_netbuf_free_single(struct uk_netbuf *m);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/uknetdev/netbuf.c b/lib/uknetdev/netbuf.c
index c0e41cd..96a5f68 100644
--- a/lib/uknetdev/netbuf.c
+++ b/lib/uknetdev/netbuf.c
@@ -33,6 +33,7 @@
*/
#include <uk/netbuf.h>
#include <uk/essentials.h>
+#include <uk/print.h>
/* Used to align netbuf's priv and data areas to `long long` data type */
#define NETBUF_ADDR_ALIGNMENT (sizeof(long long))
@@ -241,3 +242,51 @@ void uk_netbuf_append(struct uk_netbuf *head,
headtail->next = tail;
tail->prev = headtail;
}
+
+void uk_netbuf_free_single(struct uk_netbuf *m)
+{
+ struct uk_alloc *a;
+
+ UK_ASSERT(m);
+
+ /* Decrease refcount and call destructor and free up memory
+ * when last reference was released.
+ */
+ if (uk_refcount_release(&m->refcount) == 1) {
+ uk_pr_debug("Freeing netbuf %p (next: %p)\n", m, m->next);
+
+ /* Disconnect this netbuf from the chain. */
+ uk_netbuf_disconnect(m);
+
+ /* Copy the reference of the allocator in case
+ * the destructor is free'ing up our memory
+ * (e.g., uk_netbuf_init_indir() used).
+ * In such a case `a` should be (NULL), however
+ * we need to access it for a check after we have
+ * called the destructor.
+ */
+ a = m->_a;
+
+ if (m->dtor)
+ m->dtor(m);
+ if (a)
+ uk_free(a, m);
+ } else {
+ uk_pr_debug("Not freeing netbuf %p (next: %p): refcount greater
than 1",
+ m, m->next);
+ }
+}
+
+void uk_netbuf_free(struct uk_netbuf *m)
+{
+ struct uk_netbuf *n;
+
+ UK_ASSERT(m);
+ UK_ASSERT(!m->prev);
+
+ while (m != NULL) {
+ n = m->next;
+ uk_netbuf_free_single(m);
+ m = n;
+ }
+}
--
2.7.4
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |