Initial commit
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
207
src/utils/utils_list.h
Normal file
207
src/utils/utils_list.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright(c) 2012-2018 Intel Corporation
|
||||
* SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
*/
|
||||
|
||||
#ifndef __UTILS_LIST_H__
|
||||
#define __UTILS_LIST_H__
|
||||
|
||||
#include "ocf_env.h"
|
||||
#include "../ocf_ctx_priv.h"
|
||||
#include "ocf/ocf_cache.h"
|
||||
|
||||
#define OCF_LST_DBG 1
|
||||
|
||||
#if 1 == OCF_LST_DBG
|
||||
#define OCF_LST_DBG_ON(lst, cond) ({ \
|
||||
if (cond) { \
|
||||
ocf_log(ocf_cache_get_ctx(lst->cache), log_crit, \
|
||||
"OCF list critical problem (%s:%u)\n", \
|
||||
__func__, __LINE__); \
|
||||
ocf_log_stack_trace(ocf_cache_get_ctx(lst->cache)); \
|
||||
} \
|
||||
})
|
||||
#else
|
||||
#define OCF_LST_DBG_ON(lst, cond)
|
||||
#endif
|
||||
|
||||
#define OCF_LST_ENTRY_OUT(lst) ((lst)->invalid + 1)
|
||||
|
||||
struct ocf_lst_entry {
|
||||
ocf_cache_line_t next;
|
||||
ocf_cache_line_t prev;
|
||||
};
|
||||
|
||||
typedef struct ocf_lst_entry *(*ocf_mlst_getter)(
|
||||
struct ocf_cache *cache, ocf_cache_line_t idx);
|
||||
|
||||
typedef int (*ocf_mlst_cmp)(struct ocf_cache *cache,
|
||||
struct ocf_lst_entry *e1, struct ocf_lst_entry *e2);
|
||||
|
||||
struct ocf_lst {
|
||||
struct ocf_lst_entry *head;
|
||||
ocf_cache_line_t invalid;
|
||||
ocf_mlst_getter getter;
|
||||
ocf_mlst_cmp cmp;
|
||||
struct ocf_cache *cache;
|
||||
|
||||
struct {
|
||||
uint32_t active : 1;
|
||||
} flags;
|
||||
};
|
||||
|
||||
static inline void ocf_lst_init_entry(struct ocf_lst *lst,
|
||||
struct ocf_lst_entry *entry)
|
||||
{
|
||||
entry->next = entry->prev = OCF_LST_ENTRY_OUT(lst);
|
||||
}
|
||||
|
||||
static inline bool ocf_lst_is_entry(struct ocf_lst *lst,
|
||||
struct ocf_lst_entry *entry)
|
||||
{
|
||||
if (entry->next == OCF_LST_ENTRY_OUT(lst) &&
|
||||
entry->prev == OCF_LST_ENTRY_OUT(lst))
|
||||
return false;
|
||||
|
||||
if (entry->next < OCF_LST_ENTRY_OUT(lst) &&
|
||||
entry->prev < OCF_LST_ENTRY_OUT(lst))
|
||||
return true;
|
||||
|
||||
ENV_BUG();
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ocf_lst_init(struct ocf_cache *cache,
|
||||
struct ocf_lst *lst, ocf_cache_line_t invalid,
|
||||
ocf_mlst_getter getter, ocf_mlst_cmp cmp)
|
||||
{
|
||||
ocf_cache_line_t idx;
|
||||
|
||||
ENV_BUG_ON(env_memset(lst, sizeof(*lst), 0));
|
||||
|
||||
lst->head = getter(cache, invalid);
|
||||
lst->head->next = invalid;
|
||||
lst->head->prev = invalid;
|
||||
lst->invalid = invalid;
|
||||
lst->getter = getter;
|
||||
lst->cmp = cmp;
|
||||
lst->cache = cache;
|
||||
|
||||
for (idx = 0; idx < lst->invalid; idx++) {
|
||||
struct ocf_lst_entry *entry = getter(cache, idx);
|
||||
|
||||
ocf_lst_init_entry(lst, entry);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ocf_lst_add_after(struct ocf_lst *lst,
|
||||
ocf_cache_line_t at, ocf_cache_line_t idx)
|
||||
{
|
||||
struct ocf_lst_entry *after = lst->getter(lst->cache, at);
|
||||
struct ocf_lst_entry *next = lst->getter(lst->cache, after->next);
|
||||
struct ocf_lst_entry *this = lst->getter(lst->cache, idx);
|
||||
|
||||
OCF_LST_DBG_ON(lst, ocf_lst_is_entry(lst, this));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, after));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, next));
|
||||
|
||||
this->next = after->next;
|
||||
this->prev = at;
|
||||
after->next = idx;
|
||||
next->prev = idx;
|
||||
}
|
||||
|
||||
static inline void ocf_lst_add_before(struct ocf_lst *lst,
|
||||
ocf_cache_line_t at, ocf_cache_line_t idx)
|
||||
{
|
||||
struct ocf_lst_entry *before = lst->getter(lst->cache, at);
|
||||
struct ocf_lst_entry *prev = lst->getter(lst->cache, before->prev);
|
||||
struct ocf_lst_entry *this = lst->getter(lst->cache, idx);
|
||||
|
||||
OCF_LST_DBG_ON(lst, ocf_lst_is_entry(lst, this));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, before));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, prev));
|
||||
|
||||
this->next = at;
|
||||
this->prev = before->prev;
|
||||
before->prev = idx;
|
||||
prev->next = idx;
|
||||
}
|
||||
|
||||
static inline void ocf_lst_add(struct ocf_lst *lst, ocf_cache_line_t idx)
|
||||
{
|
||||
struct ocf_lst_entry *this = lst->getter(lst->cache, idx);
|
||||
struct ocf_lst_entry *next = lst->getter(lst->cache, lst->head->next);
|
||||
|
||||
OCF_LST_DBG_ON(lst, ocf_lst_is_entry(lst, this));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, next));
|
||||
|
||||
this->next = lst->head->next;
|
||||
next->prev = idx;
|
||||
lst->head->next = idx;
|
||||
this->prev = lst->invalid;
|
||||
}
|
||||
|
||||
static inline void ocf_lst_add_tail(struct ocf_lst *lst, ocf_cache_line_t idx)
|
||||
{
|
||||
struct ocf_lst_entry *this = lst->getter(lst->cache, idx);
|
||||
struct ocf_lst_entry *prev = lst->getter(lst->cache, lst->head->prev);
|
||||
|
||||
OCF_LST_DBG_ON(lst, ocf_lst_is_entry(lst, this));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, prev));
|
||||
|
||||
this->next = lst->invalid;
|
||||
this->prev = lst->head->prev;
|
||||
prev->next = idx;
|
||||
lst->head->prev = idx;
|
||||
}
|
||||
|
||||
static inline void ocf_lst_del(struct ocf_lst *lst, ocf_cache_line_t idx)
|
||||
{
|
||||
struct ocf_lst_entry *this = lst->getter(lst->cache, idx);
|
||||
struct ocf_lst_entry *next = lst->getter(lst->cache, this->next);
|
||||
struct ocf_lst_entry *prev = lst->getter(lst->cache, this->prev);
|
||||
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, this));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, next));
|
||||
OCF_LST_DBG_ON(lst, !ocf_lst_is_entry(lst, prev));
|
||||
|
||||
prev->next = this->next;
|
||||
next->prev = this->prev;
|
||||
|
||||
ocf_lst_init_entry(lst, this);
|
||||
}
|
||||
|
||||
static inline ocf_cache_line_t ocf_lst_head(struct ocf_lst *lst)
|
||||
{
|
||||
return lst->head->next;
|
||||
}
|
||||
|
||||
static inline ocf_cache_line_t ocf_lst_tail(struct ocf_lst *lst)
|
||||
{
|
||||
return lst->head->prev;
|
||||
}
|
||||
|
||||
static inline bool ocf_lst_empty(struct ocf_lst *lst)
|
||||
{
|
||||
if (lst->head->next == lst->invalid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void ocf_lst_sort(struct ocf_lst *lst);
|
||||
|
||||
#define for_each_lst(lst, entry, id) \
|
||||
for (id = (lst)->head->next, entry = (lst)->getter((lst)->cache, id); \
|
||||
entry != (lst)->head; id = entry->next, \
|
||||
entry = (lst)->getter((lst)->cache, id))
|
||||
|
||||
#define for_each_lst_entry(lst, entry, id, type, member) \
|
||||
for (id = (lst)->head->next, \
|
||||
entry = container_of((lst)->getter((lst)->cache, id), type, member); \
|
||||
entry != container_of((lst)->head, type, member); \
|
||||
id = entry->member.next, \
|
||||
entry = container_of((lst)->getter((lst)->cache, id), type, member))
|
||||
|
||||
#endif /* __UTILS_LIST_H__ */
|
Reference in New Issue
Block a user