#include <linux/llist.h>

#ifndef COMPAT_DETECT_LLIST_DEL_FIRST_THIS_6_7

bool llist_del_first_this(struct llist_head *head,
			  struct llist_node *this)
{
	struct llist_node *entry, *next;

	/* acquire ensures orderig wrt try_cmpxchg() is llist_del_first() */
	entry = smp_load_acquire(&head->first);
	do {
		if (entry != this)
			return false;
		next = READ_ONCE(entry->next);
	} while (!try_cmpxchg(&head->first, &entry, next));

	return true;
}
EXPORT_SYMBOL_GPL(llist_del_first_this);

#endif /* COMPAT_DETECT_LLIST_DEL_FIRST_THIS_6_7 */

#ifndef COMPAT_DETECT___LWQ_DEQUEUE

#include <linux/lwq.h>

struct llist_node *__lwq_dequeue(struct lwq *q)
{
	struct llist_node *this;

	if (lwq_empty(q))
		return NULL;
	spin_lock(&q->lock);
	this = q->ready;
	if (!this && !llist_empty(&q->new)) {
		/* ensure queue doesn't appear transiently lwq_empty */
		smp_store_release(&q->ready, (void *)1);
		this = llist_reverse_order(llist_del_all(&q->new));
		if (!this)
			q->ready = NULL;
	}
	if (this)
		q->ready = llist_next(this);
	spin_unlock(&q->lock);
	return this;
}
EXPORT_SYMBOL_GPL(__lwq_dequeue);

/**
 * lwq_dequeue_all - dequeue all currently enqueued objects
 * @q:	the queue to dequeue from
 *
 * Remove and return a linked list of llist_nodes of all the objects that were
 * in the queue. The first on the list will be the object that was least
 * recently enqueued.
 */
struct llist_node *lwq_dequeue_all(struct lwq *q)
{
	struct llist_node *r, *t, **ep;

	if (lwq_empty(q))
		return NULL;

	spin_lock(&q->lock);
	r = q->ready;
	q->ready = NULL;
	t = llist_del_all(&q->new);
	spin_unlock(&q->lock);
	ep = &r;
	while (*ep)
		ep = &(*ep)->next;
	*ep = llist_reverse_order(t);
	return r;
}
EXPORT_SYMBOL_GPL(lwq_dequeue_all);

#endif
