root/lib/llist.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. llist_add_batch
  2. llist_del_first
  3. llist_reverse_order

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Lock-less NULL terminated single linked list
   4  *
   5  * The basic atomic operation of this list is cmpxchg on long.  On
   6  * architectures that don't have NMI-safe cmpxchg implementation, the
   7  * list can NOT be used in NMI handlers.  So code that uses the list in
   8  * an NMI handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
   9  *
  10  * Copyright 2010,2011 Intel Corp.
  11  *   Author: Huang Ying <ying.huang@intel.com>
  12  */
  13 #include <linux/kernel.h>
  14 #include <linux/export.h>
  15 #include <linux/llist.h>
  16 
  17 
  18 /**
  19  * llist_add_batch - add several linked entries in batch
  20  * @new_first:  first entry in batch to be added
  21  * @new_last:   last entry in batch to be added
  22  * @head:       the head for your lock-less list
  23  *
  24  * Return whether list is empty before adding.
  25  */
  26 bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
  27                      struct llist_head *head)
  28 {
  29         struct llist_node *first;
  30 
  31         do {
  32                 new_last->next = first = READ_ONCE(head->first);
  33         } while (cmpxchg(&head->first, first, new_first) != first);
  34 
  35         return !first;
  36 }
  37 EXPORT_SYMBOL_GPL(llist_add_batch);
  38 
  39 /**
  40  * llist_del_first - delete the first entry of lock-less list
  41  * @head:       the head for your lock-less list
  42  *
  43  * If list is empty, return NULL, otherwise, return the first entry
  44  * deleted, this is the newest added one.
  45  *
  46  * Only one llist_del_first user can be used simultaneously with
  47  * multiple llist_add users without lock.  Because otherwise
  48  * llist_del_first, llist_add, llist_add (or llist_del_all, llist_add,
  49  * llist_add) sequence in another user may change @head->first->next,
  50  * but keep @head->first.  If multiple consumers are needed, please
  51  * use llist_del_all or use lock between consumers.
  52  */
  53 struct llist_node *llist_del_first(struct llist_head *head)
  54 {
  55         struct llist_node *entry, *old_entry, *next;
  56 
  57         entry = smp_load_acquire(&head->first);
  58         for (;;) {
  59                 if (entry == NULL)
  60                         return NULL;
  61                 old_entry = entry;
  62                 next = READ_ONCE(entry->next);
  63                 entry = cmpxchg(&head->first, old_entry, next);
  64                 if (entry == old_entry)
  65                         break;
  66         }
  67 
  68         return entry;
  69 }
  70 EXPORT_SYMBOL_GPL(llist_del_first);
  71 
  72 /**
  73  * llist_reverse_order - reverse order of a llist chain
  74  * @head:       first item of the list to be reversed
  75  *
  76  * Reverse the order of a chain of llist entries and return the
  77  * new first entry.
  78  */
  79 struct llist_node *llist_reverse_order(struct llist_node *head)
  80 {
  81         struct llist_node *new_head = NULL;
  82 
  83         while (head) {
  84                 struct llist_node *tmp = head;
  85                 head = head->next;
  86                 tmp->next = new_head;
  87                 new_head = tmp;
  88         }
  89 
  90         return new_head;
  91 }
  92 EXPORT_SYMBOL_GPL(llist_reverse_order);

/* [<][>][^][v][top][bottom][index][help] */