vhost: un-inline dirty pages logging functions
[dpdk.git] / lib / librte_stack / rte_stack.h
index 42d0427..fe048f0 100644 (file)
@@ -20,6 +20,7 @@
 extern "C" {
 #endif
 
+#include <rte_atomic.h>
 #include <rte_compat.h>
 #include <rte_debug.h>
 #include <rte_errno.h>
@@ -32,6 +33,35 @@ extern "C" {
 #define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \
                           sizeof(RTE_STACK_MZ_PREFIX) + 1)
 
+struct rte_stack_lf_elem {
+       void *data;                     /**< Data pointer */
+       struct rte_stack_lf_elem *next; /**< Next pointer */
+};
+
+struct rte_stack_lf_head {
+       struct rte_stack_lf_elem *top; /**< Stack top */
+       uint64_t cnt; /**< Modification counter for avoiding ABA problem */
+};
+
+struct rte_stack_lf_list {
+       /** List head */
+       struct rte_stack_lf_head head __rte_aligned(16);
+       /** List len */
+       rte_atomic64_t len;
+};
+
+/* Structure containing two lock-free LIFO lists: the stack itself and a list
+ * of free linked-list elements.
+ */
+struct rte_stack_lf {
+       /** LIFO list of elements */
+       struct rte_stack_lf_list used __rte_cache_aligned;
+       /** LIFO list of free elements */
+       struct rte_stack_lf_list free __rte_cache_aligned;
+       /** LIFO elements */
+       struct rte_stack_lf_elem elems[] __rte_cache_aligned;
+};
+
 /* Structure containing the LIFO, its current length, and a lock for mutual
  * exclusion.
  */
@@ -51,10 +81,21 @@ struct rte_stack {
        const struct rte_memzone *memzone;
        uint32_t capacity; /**< Usable size of the stack. */
        uint32_t flags; /**< Flags supplied at creation. */
-       struct rte_stack_std stack_std; /**< LIFO structure. */
+       RTE_STD_C11
+       union {
+               struct rte_stack_lf stack_lf; /**< Lock-free LIFO structure. */
+               struct rte_stack_std stack_std; /**< LIFO structure. */
+       };
 } __rte_cache_aligned;
 
+/**
+ * The stack uses lock-free push and pop functions. This flag is only
+ * supported on x86_64 platforms, currently.
+ */
+#define RTE_STACK_F_LF 0x0001
+
 #include "rte_stack_std.h"
+#include "rte_stack_lf.h"
 
 /**
  * @warning
@@ -77,7 +118,10 @@ rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n)
        RTE_ASSERT(s != NULL);
        RTE_ASSERT(obj_table != NULL);
 
-       return __rte_stack_std_push(s, obj_table, n);
+       if (s->flags & RTE_STACK_F_LF)
+               return __rte_stack_lf_push(s, obj_table, n);
+       else
+               return __rte_stack_std_push(s, obj_table, n);
 }
 
 /**
@@ -101,7 +145,10 @@ rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n)
        RTE_ASSERT(s != NULL);
        RTE_ASSERT(obj_table != NULL);
 
-       return __rte_stack_std_pop(s, obj_table, n);
+       if (s->flags & RTE_STACK_F_LF)
+               return __rte_stack_lf_pop(s, obj_table, n);
+       else
+               return __rte_stack_std_pop(s, obj_table, n);
 }
 
 /**
@@ -120,7 +167,10 @@ rte_stack_count(struct rte_stack *s)
 {
        RTE_ASSERT(s != NULL);
 
-       return __rte_stack_std_count(s);
+       if (s->flags & RTE_STACK_F_LF)
+               return __rte_stack_lf_count(s);
+       else
+               return __rte_stack_std_count(s);
 }
 
 /**
@@ -160,7 +210,10 @@ rte_stack_free_count(struct rte_stack *s)
  *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
  *   constraint for the reserved zone.
  * @param flags
- *   Reserved for future use.
+ *   An OR of the following:
+ *    - RTE_STACK_F_LF: If this flag is set, the stack uses lock-free
+ *      variants of the push and pop functions. Otherwise, it achieves
+ *      thread-safety using a lock.
  * @return
  *   On success, the pointer to the new allocated stack. NULL on error with
  *    rte_errno set appropriately. Possible errno values include: