[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 |