Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e0fed7f authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Lee Jones
Browse files

klist: implement klist_prev()



klist_prev() gets the previous element in the list. It is useful to traverse
through the list in reverse order, for example, to provide LIFO (last in first
out) variant of access.

Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent ddef08dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -63,6 +63,7 @@ extern void klist_iter_init(struct klist *k, struct klist_iter *i);
extern void klist_iter_init_node(struct klist *k, struct klist_iter *i,
extern void klist_iter_init_node(struct klist *k, struct klist_iter *i,
				 struct klist_node *n);
				 struct klist_node *n);
extern void klist_iter_exit(struct klist_iter *i);
extern void klist_iter_exit(struct klist_iter *i);
extern struct klist_node *klist_prev(struct klist_iter *i);
extern struct klist_node *klist_next(struct klist_iter *i);
extern struct klist_node *klist_next(struct klist_iter *i);


#endif
#endif
+41 −0
Original line number Original line Diff line number Diff line
@@ -323,6 +323,47 @@ static struct klist_node *to_klist_node(struct list_head *n)
	return container_of(n, struct klist_node, n_node);
	return container_of(n, struct klist_node, n_node);
}
}


/**
 * klist_prev - Ante up prev node in list.
 * @i: Iterator structure.
 *
 * First grab list lock. Decrement the reference count of the previous
 * node, if there was one. Grab the prev node, increment its reference
 * count, drop the lock, and return that prev node.
 */
struct klist_node *klist_prev(struct klist_iter *i)
{
	void (*put)(struct klist_node *) = i->i_klist->put;
	struct klist_node *last = i->i_cur;
	struct klist_node *prev;

	spin_lock(&i->i_klist->k_lock);

	if (last) {
		prev = to_klist_node(last->n_node.prev);
		if (!klist_dec_and_del(last))
			put = NULL;
	} else
		prev = to_klist_node(i->i_klist->k_list.prev);

	i->i_cur = NULL;
	while (prev != to_klist_node(&i->i_klist->k_list)) {
		if (likely(!knode_dead(prev))) {
			kref_get(&prev->n_ref);
			i->i_cur = prev;
			break;
		}
		prev = to_klist_node(prev->n_node.prev);
	}

	spin_unlock(&i->i_klist->k_lock);

	if (put && last)
		put(last);
	return i->i_cur;
}
EXPORT_SYMBOL_GPL(klist_prev);

/**
/**
 * klist_next - Ante up next node in list.
 * klist_next - Ante up next node in list.
 * @i: Iterator structure.
 * @i: Iterator structure.