18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Lock-less NULL terminated single linked list 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * The basic atomic operation of this list is cmpxchg on long. On 68c2ecf20Sopenharmony_ci * architectures that don't have NMI-safe cmpxchg implementation, the 78c2ecf20Sopenharmony_ci * list can NOT be used in NMI handlers. So code that uses the list in 88c2ecf20Sopenharmony_ci * an NMI handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright 2010,2011 Intel Corp. 118c2ecf20Sopenharmony_ci * Author: Huang Ying <ying.huang@intel.com> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/export.h> 158c2ecf20Sopenharmony_ci#include <linux/llist.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/** 198c2ecf20Sopenharmony_ci * llist_add_batch - add several linked entries in batch 208c2ecf20Sopenharmony_ci * @new_first: first entry in batch to be added 218c2ecf20Sopenharmony_ci * @new_last: last entry in batch to be added 228c2ecf20Sopenharmony_ci * @head: the head for your lock-less list 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Return whether list is empty before adding. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_cibool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last, 278c2ecf20Sopenharmony_ci struct llist_head *head) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct llist_node *first; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci do { 328c2ecf20Sopenharmony_ci new_last->next = first = READ_ONCE(head->first); 338c2ecf20Sopenharmony_ci } while (cmpxchg(&head->first, first, new_first) != first); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return !first; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_add_batch); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/** 408c2ecf20Sopenharmony_ci * llist_del_first - delete the first entry of lock-less list 418c2ecf20Sopenharmony_ci * @head: the head for your lock-less list 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * If list is empty, return NULL, otherwise, return the first entry 448c2ecf20Sopenharmony_ci * deleted, this is the newest added one. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * Only one llist_del_first user can be used simultaneously with 478c2ecf20Sopenharmony_ci * multiple llist_add users without lock. Because otherwise 488c2ecf20Sopenharmony_ci * llist_del_first, llist_add, llist_add (or llist_del_all, llist_add, 498c2ecf20Sopenharmony_ci * llist_add) sequence in another user may change @head->first->next, 508c2ecf20Sopenharmony_ci * but keep @head->first. If multiple consumers are needed, please 518c2ecf20Sopenharmony_ci * use llist_del_all or use lock between consumers. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_cistruct llist_node *llist_del_first(struct llist_head *head) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci struct llist_node *entry, *old_entry, *next; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci entry = smp_load_acquire(&head->first); 588c2ecf20Sopenharmony_ci for (;;) { 598c2ecf20Sopenharmony_ci if (entry == NULL) 608c2ecf20Sopenharmony_ci return NULL; 618c2ecf20Sopenharmony_ci old_entry = entry; 628c2ecf20Sopenharmony_ci next = READ_ONCE(entry->next); 638c2ecf20Sopenharmony_ci entry = cmpxchg(&head->first, old_entry, next); 648c2ecf20Sopenharmony_ci if (entry == old_entry) 658c2ecf20Sopenharmony_ci break; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return entry; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_del_first); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/** 738c2ecf20Sopenharmony_ci * llist_reverse_order - reverse order of a llist chain 748c2ecf20Sopenharmony_ci * @head: first item of the list to be reversed 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * Reverse the order of a chain of llist entries and return the 778c2ecf20Sopenharmony_ci * new first entry. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_cistruct llist_node *llist_reverse_order(struct llist_node *head) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct llist_node *new_head = NULL; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci while (head) { 848c2ecf20Sopenharmony_ci struct llist_node *tmp = head; 858c2ecf20Sopenharmony_ci head = head->next; 868c2ecf20Sopenharmony_ci tmp->next = new_head; 878c2ecf20Sopenharmony_ci new_head = tmp; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return new_head; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_reverse_order); 93