1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2020, Intel Corporation */
5 * ravl_interval.c -- ravl_interval implementation
10 #include "ravl_interval.h"
11 #include "pmem2_utils.h"
13 #include "os_thread.h"
17 * ravl_interval - structure representing two points
20 struct ravl_interval
{
22 ravl_interval_min
*get_min
;
23 ravl_interval_max
*get_max
;
27 * ravl_interval_node - structure holding min, max functions and address
29 struct ravl_interval_node
{
31 ravl_interval_min
*get_min
;
32 ravl_interval_max
*get_max
;
36 * ravl_interval_compare -- compare intervals by its boundaries,
37 * no overlapping allowed
40 ravl_interval_compare(const void *lhs
, const void *rhs
)
42 const struct ravl_interval_node
*left
= lhs
;
43 const struct ravl_interval_node
*right
= rhs
;
45 if (left
->get_max(left
->addr
) <= right
->get_min(right
->addr
))
47 if (left
->get_min(left
->addr
) >= right
->get_max(right
->addr
))
53 * ravl_interval_delete - finalize the ravl interval module
56 ravl_interval_delete(struct ravl_interval
*ri
)
58 ravl_delete(ri
->tree
);
64 * ravl_interval_new -- initialize the ravl interval module
66 struct ravl_interval
*
67 ravl_interval_new(ravl_interval_min
*get_min
, ravl_interval_max
*get_max
)
70 struct ravl_interval
*interval
= pmem2_malloc(sizeof(*interval
), &ret
);
74 interval
->tree
= ravl_new_sized(ravl_interval_compare
,
75 sizeof(struct ravl_interval_node
));
76 if (!(interval
->tree
))
79 interval
->get_min
= get_min
;
80 interval
->get_max
= get_max
;
91 * ravl_interval_insert -- insert interval entry into the tree
94 ravl_interval_insert(struct ravl_interval
*ri
, void *addr
)
96 struct ravl_interval_node rin
;
98 rin
.get_min
= ri
->get_min
;
99 rin
.get_max
= ri
->get_max
;
101 if (ravl_emplace_copy(ri
->tree
, &rin
))
102 return PMEM2_E_ERRNO
;
108 * ravl_interval_remove -- remove interval entry from the tree
111 ravl_interval_remove(struct ravl_interval
*ri
, struct ravl_interval_node
*rin
)
113 struct ravl_node
*node
= ravl_find(ri
->tree
, rin
,
114 RAVL_PREDICATE_EQUAL
);
116 return PMEM2_E_MAPPING_NOT_FOUND
;
118 ravl_remove(ri
->tree
, node
);
124 * ravl_interval_find_prior_or_eq -- find overlapping interval starting prior to
125 * the current one or at the same place
127 static struct ravl_interval_node
*
128 ravl_interval_find_prior_or_eq(struct ravl
*tree
,
129 struct ravl_interval_node
*rin
)
131 struct ravl_node
*node
;
132 struct ravl_interval_node
*cur
;
134 node
= ravl_find(tree
, rin
, RAVL_PREDICATE_LESS_EQUAL
);
138 cur
= ravl_data(node
);
140 * If the end of the found interval is below the searched boundary, then
141 * this is not our interval.
143 if (cur
->get_max(cur
->addr
) <= rin
->get_min(rin
->addr
))
150 * ravl_interval_find_later -- find overlapping interval starting later than
153 static struct ravl_interval_node
*
154 ravl_interval_find_later(struct ravl
*tree
, struct ravl_interval_node
*rin
)
156 struct ravl_node
*node
;
157 struct ravl_interval_node
*cur
;
159 node
= ravl_find(tree
, rin
, RAVL_PREDICATE_GREATER
);
163 cur
= ravl_data(node
);
166 * If the beginning of the found interval is above the end of
167 * the searched range, then this is not our interval.
169 if (cur
->get_min(cur
->addr
) >= rin
->get_max(rin
->addr
))
176 * ravl_interval_find_equal -- find the interval with exact (min, max) range
178 struct ravl_interval_node
*
179 ravl_interval_find_equal(struct ravl_interval
*ri
, void *addr
)
181 struct ravl_interval_node range
;
183 range
.get_min
= ri
->get_min
;
184 range
.get_max
= ri
->get_max
;
186 struct ravl_node
*node
;
187 node
= ravl_find(ri
->tree
, &range
, RAVL_PREDICATE_EQUAL
);
191 return ravl_data(node
);
195 * ravl_interval_find -- find the earliest interval within (min, max) range
197 struct ravl_interval_node
*
198 ravl_interval_find(struct ravl_interval
*ri
, void *addr
)
200 struct ravl_interval_node range
;
202 range
.get_min
= ri
->get_min
;
203 range
.get_max
= ri
->get_max
;
205 struct ravl_interval_node
*cur
;
206 cur
= ravl_interval_find_prior_or_eq(ri
->tree
, &range
);
208 cur
= ravl_interval_find_later(ri
->tree
, &range
);
214 * ravl_interval_find_closest_prior -- find the closest interval
215 * neighbor prior to the current one
217 struct ravl_interval_node
*
218 ravl_interval_find_closest_prior(struct ravl_interval
*ri
, void *addr
)
220 struct ravl_interval_node range
;
222 range
.get_min
= ri
->get_min
;
223 range
.get_max
= ri
->get_max
;
225 struct ravl_node
*node
;
226 node
= ravl_find(ri
->tree
, &range
, RAVL_PREDICATE_LESS
);
230 return ravl_data(node
);
234 * ravl_interval_find_closest_later -- find the closest interval neighbor
235 * that occurs after the current one
237 struct ravl_interval_node
*
238 ravl_interval_find_closest_later(struct ravl_interval
*ri
, void *addr
)
240 struct ravl_interval_node range
;
242 range
.get_min
= ri
->get_min
;
243 range
.get_max
= ri
->get_max
;
245 struct ravl_node
*node
;
246 node
= ravl_find(ri
->tree
, &range
, RAVL_PREDICATE_GREATER
);
250 return ravl_data(node
);
254 * ravl_interval_data -- returns the data contained within an interval node
257 ravl_interval_data(struct ravl_interval_node
*rin
)
259 return (void *)rin
->addr
;