Makefile.am: Clean flake8-check too.
[cascardo/ovs.git] / lib / rculist.h
index 2e926de..7ba20e5 100644 (file)
@@ -26,7 +26,8 @@
  * To be RCU-friendly, the struct rculist instances must be freed via
  * ovsrcu_postpone().
  *
- * The API is almost the same as for struct list, with the following exeptions:
+ * The API is almost the same as for struct ovs_list, with the following
+ * exeptions:
  *
  * - The 'prev' pointer may not be accessed by the user.
  * - The 'next' pointer should be accessed via rculist_next() by readers, and
  * - rculist_front() returns a const pointer to accommodate for an RCU reader.
  * - rculist_splice_hidden(): Spliced elements may not have been visible to
  *   RCU readers before the operation.
- * - rculist_poison(): Immediately poisons the 'prev' pointer, and schedules
- *   ovsrcu_postpone() to poison the 'next' pointer.  This issues a memory
- *   write operation to the list element, hopefully crashing the program if
- *   the list node was freed or re-used too early.
+ * - rculist_poison(): Only poisons the 'prev' pointer.
  *
- * The following functions are variations of the struct list functions with
+ * The following functions are variations of the struct ovs_list functions with
  * similar names, but are now restricted to the writer use:
  *
  * - rculist_back_protected()
@@ -57,7 +55,7 @@
 
 /* A non-existing mutex to make it more difficult for an user to accidentally
  * keep using the 'prev' pointer.  This may be helpful when porting code from
- * struct list to rculist. */
+ * struct ovs_list to rculist. */
 extern struct ovs_mutex rculist_fake_mutex;
 
 /* Doubly linked list head or element. */
@@ -74,7 +72,7 @@ static inline const struct rculist *rculist_next(const struct rculist *);
 static inline struct rculist *rculist_next_protected(const struct rculist *);
 
 /* List initialization. */
-#define RCULIST_INITIALIZER(LIST) { LIST, OVSRCU_INITIALIZER(LIST) }
+#define RCUOVS_LIST_INITIALIZER(LIST) { LIST, OVSRCU_INITIALIZER(LIST) }
 
 static inline void rculist_init(struct rculist *list);
 static inline void rculist_poison(struct rculist *elem);
@@ -133,8 +131,6 @@ rculist_init(struct rculist *list)
 
 #define RCULIST_POISON (struct rculist *)(UINTPTR_MAX / 0xf * 0xc)
 
-void rculist_poison__(struct rculist *list);
-
 /* Initializes 'list' with pointers that will (probably) cause segfaults if
  * dereferenced and, better yet, show up clearly in a debugger. */
 static inline void
@@ -142,7 +138,19 @@ rculist_poison(struct rculist *list)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
     list->prev = RCULIST_POISON;
-    ovsrcu_postpone(rculist_poison__, list);
+}
+
+/* Initializes 'list' with pointers that will (probably) cause segfaults if
+ * dereferenced and, better yet, show up clearly in a debugger.
+ *
+ * This variant poisons also the next pointer, so this may not be called if
+ * this list element is still visible to RCU readers. */
+static inline void
+rculist_poison__(struct rculist *list)
+    OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+    rculist_poison(list);
+    ovsrcu_set_hidden(&list->next, RCULIST_POISON);
 }
 
 /* rculist insertion. */
@@ -216,10 +224,7 @@ rculist_replace(struct rculist *element, struct rculist *position)
     position_next->prev = element;
     element->prev = position->prev;
     ovsrcu_set(&element->prev->next, element);
-
-#ifndef NDEBUG
-    rculist_poison(position); /* XXX: Some overhead due to ovsrcu_postpone() */
-#endif
+    rculist_poison(position);
 }
 
 /* Initializes 'dst' with the contents of 'src', compensating for moving it
@@ -243,14 +248,12 @@ rculist_move(struct rculist *dst, struct rculist *src)
     } else {
         rculist_init(dst);
     }
-
-#ifndef NDEBUG
-    rculist_poison(src); /* XXX: Some overhead due to ovsrcu_postpone() */
-#endif
+    rculist_poison(src);
 }
 
 /* Removes 'elem' from its list and returns the element that followed it.
- * Undefined behavior if 'elem' is not in a list.
+ * Has no effect when 'elem' is initialized, but not in a list.
+ * Undefined behavior if 'elem' is not initialized.
  *
  * Afterward, 'elem' is not linked to from the list any more, but still links
  * to the nodes in the list, and may still be referenced by other threads until
@@ -266,10 +269,7 @@ rculist_remove(struct rculist *elem)
 
     elem_next->prev = elem->prev;
     ovsrcu_set(&elem->prev->next, elem_next);
-
-#ifndef NDEBUG
-    rculist_poison(elem); /* XXX: Some overhead due to ovsrcu_postpone() */
-#endif
+    rculist_poison(elem);
     return elem_next;
 }
 
@@ -318,16 +318,12 @@ rculist_front(const struct rculist *list)
 }
 
 /* Returns the back element in 'list_'.
- * Undefined behavior if 'list_' is empty. */
+ * Returns the 'list_' itself, if 'list_' is empty. */
 static inline struct rculist *
-rculist_back_protected(const struct rculist *list_)
+rculist_back_protected(const struct rculist *list)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
-    struct rculist *list = CONST_CAST(struct rculist *, list_);
-
-    ovs_assert(!rculist_is_empty(list));
-
-    return list->prev;
+    return CONST_CAST(struct rculist *, list)->prev;
 }
 
 /* Returns the number of elements in 'list'.