Update Linux's list.h
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 9 Apr 2018 18:29:55 +0000 (14:29 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:37:05 +0000 (14:37 -0400)
Up to date with 569dbb88e80d ("Linux 4.13").

Basically generate a patch on Linux:

$ git diff bc208e0ee0f4..HEAD include/linux/list.h > ~/foo.patch

And apply it to Akaros:

$ cd kern/include/
$ patch -p3 < ~/foo.patch

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/list.h

index 118cd63..1985ccb 100644 (file)
@@ -1,6 +1,6 @@
 /* Linux's list definitions.
  *
- * From commit bc208e0ee0f46744aac95c29366144271a6962bb */
+ * Up to date with commit 569dbb88e80d ("Linux 4.13") */
 
 #pragma once
 
@@ -52,31 +52,46 @@ struct hlist_node {
 
 static inline void INIT_LIST_HEAD(struct list_head *list)
 {
-       list->next = list;
+       WRITE_ONCE(list->next, list);
        list->prev = list;
 }
 
+#ifdef CONFIG_DEBUG_LIST
+extern bool __list_add_valid(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next);
+extern bool __list_del_entry_valid(struct list_head *entry);
+#else
+static inline bool __list_add_valid(struct list_head *new,
+                               struct list_head *prev,
+                               struct list_head *next)
+{
+       return true;
+}
+static inline bool __list_del_entry_valid(struct list_head *entry)
+{
+       return true;
+}
+#endif
+
 /*
  * Insert a new entry between two known consecutive entries.
  *
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
 {
+       if (!__list_add_valid(new, prev, next))
+               return;
+
        next->prev = new;
        new->next = next;
        new->prev = prev;
-       prev->next = new;
+       WRITE_ONCE(prev->next, new);
 }
-#else
-extern void __list_add(struct list_head *new,
-                             struct list_head *prev,
-                             struct list_head *next);
-#endif
 
 /**
  * list_add - add a new entry
@@ -115,7 +130,7 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
 static inline void __list_del(struct list_head * prev, struct list_head * next)
 {
        next->prev = prev;
-       prev->next = next;
+       WRITE_ONCE(prev->next, next);
 }
 
 /**
@@ -124,22 +139,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
  * Note: list_empty() on entry does not return true after this, the entry is
  * in an undefined state.
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_del_entry(struct list_head *entry)
 {
+       if (!__list_del_entry_valid(entry))
+               return;
+
        __list_del(entry->prev, entry->next);
 }
 
 static inline void list_del(struct list_head *entry)
 {
-       __list_del(entry->prev, entry->next);
+       __list_del_entry(entry);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
 }
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
 
 /**
  * list_replace - replace old entry by new one
@@ -214,7 +227,7 @@ static inline int list_is_last(const struct list_head *list,
  */
 static inline int list_empty(const struct list_head *head)
 {
-       return head->next == head;
+       return READ_ONCE(head->next) == head;
 }
 
 /**
@@ -409,8 +422,11 @@ static inline void list_splice_tail_init(struct list_head *list,
  *
  * Note that if the list is empty, it returns NULL.
  */
-#define list_first_entry_or_null(ptr, type, member) \
-       (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+#define list_first_entry_or_null(ptr, type, member) ({ \
+       struct list_head *head__ = (ptr); \
+       struct list_head *pos__ = READ_ONCE(head__->next); \
+       pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
+})
 
 /**
  * list_next_entry - get the next element in list
@@ -539,6 +555,19 @@ static inline void list_splice_tail_init(struct list_head *list,
             pos = list_next_entry(pos, member))
 
 /**
+ * list_for_each_entry_from_reverse - iterate backwards over list of given type
+ *                                    from the current point
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from_reverse(pos, head, member)            \
+       for (; &pos->member != (head);                                  \
+            pos = list_prev_entry(pos, member))
+
+/**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
  * @pos:       the type * to use as a loop cursor.
  * @n:         another type * to use as temporary storage
@@ -636,14 +665,15 @@ static inline int hlist_unhashed(const struct hlist_node *h)
 
 static inline int hlist_empty(const struct hlist_head *h)
 {
-       return !h->first;
+       return !READ_ONCE(h->first);
 }
 
 static inline void __hlist_del(struct hlist_node *n)
 {
        struct hlist_node *next = n->next;
        struct hlist_node **pprev = n->pprev;
-       *pprev = next;
+
+       WRITE_ONCE(*pprev, next);
        if (next)
                next->pprev = pprev;
 }
@@ -669,7 +699,7 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
        n->next = first;
        if (first)
                first->pprev = &n->next;
-       h->first = n;
+       WRITE_ONCE(h->first, n);
        n->pprev = &h->first;
 }
 
@@ -680,14 +710,14 @@ static inline void hlist_add_before(struct hlist_node *n,
        n->pprev = next->pprev;
        n->next = next;
        next->pprev = &n->next;
-       *(n->pprev) = n;
+       WRITE_ONCE(*(n->pprev), n);
 }
 
 static inline void hlist_add_behind(struct hlist_node *n,
                                    struct hlist_node *prev)
 {
        n->next = prev->next;
-       prev->next = n;
+       WRITE_ONCE(prev->next, n);
        n->pprev = &prev->next;
 
        if (n->next)
@@ -700,6 +730,21 @@ static inline void hlist_add_fake(struct hlist_node *n)
        n->pprev = &n->next;
 }
 
+static inline bool hlist_fake(struct hlist_node *h)
+{
+       return h->pprev == &h->next;
+}
+
+/*
+ * Check whether the node is the only node of the head without
+ * accessing head:
+ */
+static inline bool
+hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
+{
+       return !n->next && n->pprev == &h->first;
+}
+
 /*
  * Move a list from one list head to another. Fixup the pprev
  * reference of the first entry if it exists.