llist.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Lock-less NULL terminated single linked list
  3. *
  4. * The basic atomic operation of this list is cmpxchg on long. On
  5. * architectures that don't have NMI-safe cmpxchg implementation, the
  6. * list can NOT be used in NMI handler. So code uses the list in NMI
  7. * handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
  8. *
  9. * Copyright 2010,2011 Intel Corp.
  10. * Author: Huang Ying <ying.huang@intel.com>
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License version
  14. * 2 as published by the Free Software Foundation;
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. */
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/llist.h>
  29. #include <asm/system.h>
  30. /**
  31. * llist_add - add a new entry
  32. * @new: new entry to be added
  33. * @head: the head for your lock-less list
  34. */
  35. void llist_add(struct llist_node *new, struct llist_head *head)
  36. {
  37. struct llist_node *entry, *old_entry;
  38. #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
  39. BUG_ON(in_nmi());
  40. #endif
  41. entry = head->first;
  42. do {
  43. old_entry = entry;
  44. new->next = entry;
  45. cpu_relax();
  46. } while ((entry = cmpxchg(&head->first, old_entry, new)) != old_entry);
  47. }
  48. EXPORT_SYMBOL_GPL(llist_add);
  49. /**
  50. * llist_add_batch - add several linked entries in batch
  51. * @new_first: first entry in batch to be added
  52. * @new_last: last entry in batch to be added
  53. * @head: the head for your lock-less list
  54. */
  55. void llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
  56. struct llist_head *head)
  57. {
  58. struct llist_node *entry, *old_entry;
  59. #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
  60. BUG_ON(in_nmi());
  61. #endif
  62. entry = head->first;
  63. do {
  64. old_entry = entry;
  65. new_last->next = entry;
  66. cpu_relax();
  67. } while ((entry = cmpxchg(&head->first, old_entry, new_first)) != old_entry);
  68. }
  69. EXPORT_SYMBOL_GPL(llist_add_batch);
  70. /**
  71. * llist_del_first - delete the first entry of lock-less list
  72. * @head: the head for your lock-less list
  73. *
  74. * If list is empty, return NULL, otherwise, return the first entry
  75. * deleted, this is the newest added one.
  76. *
  77. * Only one llist_del_first user can be used simultaneously with
  78. * multiple llist_add users without lock. Because otherwise
  79. * llist_del_first, llist_add, llist_add (or llist_del_all, llist_add,
  80. * llist_add) sequence in another user may change @head->first->next,
  81. * but keep @head->first. If multiple consumers are needed, please
  82. * use llist_del_all or use lock between consumers.
  83. */
  84. struct llist_node *llist_del_first(struct llist_head *head)
  85. {
  86. struct llist_node *entry, *old_entry, *next;
  87. #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
  88. BUG_ON(in_nmi());
  89. #endif
  90. entry = head->first;
  91. do {
  92. if (entry == NULL)
  93. return NULL;
  94. old_entry = entry;
  95. next = entry->next;
  96. cpu_relax();
  97. } while ((entry = cmpxchg(&head->first, old_entry, next)) != old_entry);
  98. return entry;
  99. }
  100. EXPORT_SYMBOL_GPL(llist_del_first);
  101. /**
  102. * llist_del_all - delete all entries from lock-less list
  103. * @head: the head of lock-less list to delete all entries
  104. *
  105. * If list is empty, return NULL, otherwise, delete all entries and
  106. * return the pointer to the first entry. The order of entries
  107. * deleted is from the newest to the oldest added one.
  108. */
  109. struct llist_node *llist_del_all(struct llist_head *head)
  110. {
  111. #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
  112. BUG_ON(in_nmi());
  113. #endif
  114. return xchg(&head->first, NULL);
  115. }
  116. EXPORT_SYMBOL_GPL(llist_del_all);