2022-06-03 19:15:11 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2022-11-01 20:26:26 +00:00
|
|
|
* Copyright (C) 2018 Intel Corporation.
|
2018-09-20 16:54:49 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __OCF_LIST_H__
|
|
|
|
#define __OCF_LIST_H__
|
|
|
|
|
|
|
|
#define LIST_POISON1 ((void *) 0x00100100)
|
|
|
|
#define LIST_POISON2 ((void *) 0x00200200)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List entry structure mimicking linux kernel based one.
|
|
|
|
*/
|
|
|
|
struct list_head {
|
|
|
|
struct list_head *next;
|
|
|
|
struct list_head *prev;
|
2021-06-25 07:11:42 +00:00
|
|
|
} __attribute__((aligned(64)));
|
2018-09-20 16:54:49 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* start an empty list
|
|
|
|
*/
|
|
|
|
#define INIT_LIST_HEAD(l) { (l)->prev = l; (l)->next = l; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add item to list head.
|
|
|
|
* @param it list entry to be added
|
|
|
|
* @param l1 list main node (head)
|
|
|
|
*/
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline void
|
|
|
|
list_add(struct list_head *it, struct list_head *l1)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
it->prev = l1;
|
|
|
|
it->next = l1->next;
|
|
|
|
|
|
|
|
l1->next->prev = it;
|
|
|
|
l1->next = it;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add item it to tail.
|
|
|
|
* @param it list entry to be added
|
|
|
|
* @param l1 list main node (head)
|
|
|
|
*/
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline void
|
|
|
|
list_add_tail(struct list_head *it, struct list_head *l1)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
it->prev = l1->prev;
|
|
|
|
it->next = l1;
|
|
|
|
|
|
|
|
l1->prev->next = it;
|
|
|
|
l1->prev = it;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* check if a list is empty (return true)
|
|
|
|
*/
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline int
|
|
|
|
list_empty(struct list_head *it)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
return it->next == it;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* delete an entry from a list
|
|
|
|
*/
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline void
|
|
|
|
list_del(struct list_head *it)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
it->next->prev = it->prev;
|
|
|
|
it->prev->next = it->next;
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline void
|
|
|
|
list_move_tail(struct list_head *list,
|
|
|
|
struct list_head *head)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
list_del(list);
|
|
|
|
list_add_tail(list, head);
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
static inline void
|
|
|
|
list_move(struct list_head *list,
|
|
|
|
struct list_head *head)
|
2018-09-20 16:54:49 +00:00
|
|
|
{
|
|
|
|
list_del(list);
|
|
|
|
list_add(list, head);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extract an entry.
|
|
|
|
* @param list_head_i list head item, from which entry is extracted
|
|
|
|
* @param item_type type (struct) of list entry
|
|
|
|
* @param field_name name of list_head field within item_type
|
|
|
|
*/
|
|
|
|
#define list_entry(list_head_i, item_type, field_name) \
|
|
|
|
(item_type *)(((void*)(list_head_i)) - offsetof(item_type, field_name))
|
|
|
|
|
|
|
|
#define list_first_entry(list_head_i, item_type, field_name) \
|
|
|
|
list_entry((list_head_i)->next, item_type, field_name)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param iterator uninitialized list_head pointer, to be used as iterator
|
|
|
|
* @param plist list head (main node)
|
|
|
|
*/
|
|
|
|
#define list_for_each(iterator, plist) \
|
|
|
|
for (iterator = (plist)->next; \
|
|
|
|
(iterator)->next != (plist)->next; \
|
|
|
|
iterator = (iterator)->next)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Safe version of list_for_each which works even if entries are deleted during
|
|
|
|
* loop.
|
|
|
|
* @param iterator uninitialized list_head pointer, to be used as iterator
|
|
|
|
* @param q another uninitialized list_head, used as helper
|
|
|
|
* @param plist list head (main node)
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Algorithm handles situation, where q is deleted.
|
|
|
|
* consider in example 3 element list with header h:
|
|
|
|
*
|
|
|
|
* h -> 1 -> 2 -> 3 ->
|
|
|
|
*1. i q
|
|
|
|
*
|
|
|
|
*2. i q
|
|
|
|
*
|
|
|
|
*3. q i
|
|
|
|
*/
|
|
|
|
#define list_for_each_safe(iterator, q, plist) \
|
|
|
|
for (iterator = (q = (plist)->next->next)->prev; \
|
|
|
|
(q) != (plist)->next; \
|
|
|
|
iterator = (q = (q)->next)->prev)
|
|
|
|
|
|
|
|
#define _list_entry_helper(item, head, field_name) list_entry(head, typeof(*item), field_name)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterate over list entries.
|
|
|
|
* @param list pointer to list item (iterator)
|
|
|
|
* @param plist pointer to list_head item
|
|
|
|
* @param field_name name of list_head field in list entry
|
|
|
|
*/
|
|
|
|
#define list_for_each_entry(item, plist, field_name) \
|
|
|
|
for (item = _list_entry_helper(item, (plist)->next, field_name); \
|
|
|
|
_list_entry_helper(item, (item)->field_name.next, field_name) !=\
|
|
|
|
_list_entry_helper(item, (plist)->next, field_name); \
|
|
|
|
item = _list_entry_helper(item, (item)->field_name.next, field_name))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Safe version of list_for_each_entry which works even if entries are deleted
|
|
|
|
* during loop.
|
|
|
|
* @param list pointer to list item (iterator)
|
|
|
|
* @param q another pointer to list item, used as helper
|
|
|
|
* @param plist pointer to list_head item
|
|
|
|
* @param field_name name of list_head field in list entry
|
|
|
|
*/
|
|
|
|
#define list_for_each_entry_safe(item, q, plist, field_name) \
|
|
|
|
for (item = _list_entry_helper(item, (plist)->next, field_name), \
|
|
|
|
q = _list_entry_helper(item, (item)->field_name.next, field_name); \
|
|
|
|
_list_entry_helper(item, (item)->field_name.next, field_name) != \
|
|
|
|
_list_entry_helper(item, (plist)->next, field_name); \
|
|
|
|
item = q, q = _list_entry_helper(q, (q)->field_name.next, field_name))
|
|
|
|
|
|
|
|
#endif
|