162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Lock-less NULL terminated single linked list 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * The basic atomic operation of this list is cmpxchg on long. On 662306a36Sopenharmony_ci * architectures that don't have NMI-safe cmpxchg implementation, the 762306a36Sopenharmony_ci * list can NOT be used in NMI handlers. So code that uses the list in 862306a36Sopenharmony_ci * an NMI handler should depend on CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Copyright 2010,2011 Intel Corp. 1162306a36Sopenharmony_ci * Author: Huang Ying <ying.huang@intel.com> 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/export.h> 1562306a36Sopenharmony_ci#include <linux/llist.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/** 1962306a36Sopenharmony_ci * llist_add_batch - add several linked entries in batch 2062306a36Sopenharmony_ci * @new_first: first entry in batch to be added 2162306a36Sopenharmony_ci * @new_last: last entry in batch to be added 2262306a36Sopenharmony_ci * @head: the head for your lock-less list 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Return whether list is empty before adding. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_cibool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last, 2762306a36Sopenharmony_ci struct llist_head *head) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct llist_node *first = READ_ONCE(head->first); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci do { 3262306a36Sopenharmony_ci new_last->next = first; 3362306a36Sopenharmony_ci } while (!try_cmpxchg(&head->first, &first, new_first)); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci return !first; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_add_batch); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/** 4062306a36Sopenharmony_ci * llist_del_first - delete the first entry of lock-less list 4162306a36Sopenharmony_ci * @head: the head for your lock-less list 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * If list is empty, return NULL, otherwise, return the first entry 4462306a36Sopenharmony_ci * deleted, this is the newest added one. 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * Only one llist_del_first user can be used simultaneously with 4762306a36Sopenharmony_ci * multiple llist_add users without lock. Because otherwise 4862306a36Sopenharmony_ci * llist_del_first, llist_add, llist_add (or llist_del_all, llist_add, 4962306a36Sopenharmony_ci * llist_add) sequence in another user may change @head->first->next, 5062306a36Sopenharmony_ci * but keep @head->first. If multiple consumers are needed, please 5162306a36Sopenharmony_ci * use llist_del_all or use lock between consumers. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistruct llist_node *llist_del_first(struct llist_head *head) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci struct llist_node *entry, *next; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci entry = smp_load_acquire(&head->first); 5862306a36Sopenharmony_ci do { 5962306a36Sopenharmony_ci if (entry == NULL) 6062306a36Sopenharmony_ci return NULL; 6162306a36Sopenharmony_ci next = READ_ONCE(entry->next); 6262306a36Sopenharmony_ci } while (!try_cmpxchg(&head->first, &entry, next)); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci return entry; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_del_first); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/** 6962306a36Sopenharmony_ci * llist_reverse_order - reverse order of a llist chain 7062306a36Sopenharmony_ci * @head: first item of the list to be reversed 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * Reverse the order of a chain of llist entries and return the 7362306a36Sopenharmony_ci * new first entry. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_cistruct llist_node *llist_reverse_order(struct llist_node *head) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct llist_node *new_head = NULL; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci while (head) { 8062306a36Sopenharmony_ci struct llist_node *tmp = head; 8162306a36Sopenharmony_ci head = head->next; 8262306a36Sopenharmony_ci tmp->next = new_head; 8362306a36Sopenharmony_ci new_head = tmp; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return new_head; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(llist_reverse_order); 89