/* SPDX-License-Identifier: GPL-2.0 */


#ifndef _LINUX_LIST_PRIVATE_H
#define _LINUX_LIST_PRIVATE_H



#include <linux/compiler.h>
#include <linux/list.h>

#define __list_private_offset(type, member)					\
	((size_t)(&ACCESS_PRIVATE(((type *)0), member)))


#define list_private_entry(ptr, type, member) ({				\
	const struct list_head *__mptr = (ptr);					\
	(type *)((char *)__mptr - __list_private_offset(type, member));		\
})


#define list_private_first_entry(ptr, type, member)				\
	list_private_entry((ptr)->next, type, member)


#define list_private_last_entry(ptr, type, member)				\
	list_private_entry((ptr)->prev, type, member)


#define list_private_next_entry(pos, member)					\
	list_private_entry(ACCESS_PRIVATE(pos, member).next, typeof(*(pos)), member)


#define list_private_next_entry_circular(pos, head, member)			\
	(list_is_last(&ACCESS_PRIVATE(pos, member), head) ?			\
	list_private_first_entry(head, typeof(*(pos)), member) :		\
	list_private_next_entry(pos, member))


#define list_private_prev_entry(pos, member)					\
	list_private_entry(ACCESS_PRIVATE(pos, member).prev, typeof(*(pos)), member)


#define list_private_prev_entry_circular(pos, head, member)			\
	(list_is_first(&ACCESS_PRIVATE(pos, member), head) ?			\
	list_private_last_entry(head, typeof(*(pos)), member) :			\
	list_private_prev_entry(pos, member))


#define list_private_entry_is_head(pos, head, member)				\
	list_is_head(&ACCESS_PRIVATE(pos, member), (head))


#define list_private_for_each_entry(pos, head, member)				\
	for (pos = list_private_first_entry(head, typeof(*pos), member);	\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_next_entry(pos, member))


#define list_private_for_each_entry_reverse(pos, head, member)			\
	for (pos = list_private_last_entry(head, typeof(*pos), member);		\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_prev_entry(pos, member))


#define list_private_for_each_entry_continue(pos, head, member)			\
	for (pos = list_private_next_entry(pos, member);			\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_next_entry(pos, member))


#define list_private_for_each_entry_continue_reverse(pos, head, member)		\
	for (pos = list_private_prev_entry(pos, member);			\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_prev_entry(pos, member))


#define list_private_for_each_entry_from(pos, head, member)			\
	for (; !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_next_entry(pos, member))


#define list_private_for_each_entry_from_reverse(pos, head, member)		\
	for (; !list_private_entry_is_head(pos, head, member);			\
	     pos = list_private_prev_entry(pos, member))


#define list_private_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_private_first_entry(head, typeof(*pos), member),	\
		n = list_private_next_entry(pos, member);			\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = n, n = list_private_next_entry(n, member))


#define list_private_for_each_entry_safe_continue(pos, n, head, member)		\
	for (pos = list_private_next_entry(pos, member),			\
		n = list_private_next_entry(pos, member);			\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = n, n = list_private_next_entry(n, member))


#define list_private_for_each_entry_safe_from(pos, n, head, member)		\
	for (n = list_private_next_entry(pos, member);				\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = n, n = list_private_next_entry(n, member))


#define list_private_for_each_entry_safe_reverse(pos, n, head, member)		\
	for (pos = list_private_last_entry(head, typeof(*pos), member),		\
		n = list_private_prev_entry(pos, member);			\
	     !list_private_entry_is_head(pos, head, member);			\
	     pos = n, n = list_private_prev_entry(n, member))


#define list_private_safe_reset_next(pos, n, member)				\
	n = list_private_next_entry(pos, member)

#endif 
