aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Vainman <alexonlists@gmail.com>2010-02-01 07:58:04 +0200
committerRoland Dreier <rolandd@cisco.com>2010-03-19 11:04:10 -0700
commitc2fa381cf71148f01b4958f3e46650f55effa763 (patch)
treef286412335ce77b85406204e5dee607593526218
parent825a14116ccacaabc649745329e0b8b412cfbb08 (diff)
downloadlibibverbs-c2fa381cf71148f01b4958f3e46650f55effa763.tar.gz
Factor out range handling in ibv_madvise_range()
Clean up some code in ibv_madvise_range() by adding functions merge_ranges(), split_range() and get_start_node(). Signed-off-by: Alex Vainman <alexv@voltaire.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--src/memory.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/src/memory.c b/src/memory.c
index 53d86b7..51839e2 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -446,6 +446,49 @@ static struct ibv_mem_node *__mm_find_start(uintptr_t start, uintptr_t end)
return node;
}
+static struct ibv_mem_node *merge_ranges(struct ibv_mem_node *node,
+ struct ibv_mem_node *prev)
+{
+ prev->end = node->end;
+ prev->refcnt = node->refcnt;
+ __mm_remove(node);
+
+ return prev;
+}
+
+static struct ibv_mem_node *split_range(struct ibv_mem_node *node,
+ uintptr_t cut_line)
+{
+ struct ibv_mem_node *new_node = NULL;
+
+ new_node = malloc(sizeof *new_node);
+ if (!new_node)
+ return NULL;
+ new_node->start = cut_line;
+ new_node->end = node->end;
+ new_node->refcnt = node->refcnt;
+ node->end = cut_line - 1;
+ __mm_add(new_node);
+
+ return new_node;
+}
+
+static struct ibv_mem_node *get_start_node(uintptr_t start, uintptr_t end,
+ int inc)
+{
+ struct ibv_mem_node *node, *tmp = NULL;
+
+ node = __mm_find_start(start, end);
+ if (node->start < start)
+ node = split_range(node, start);
+ else {
+ tmp = __mm_prev(node);
+ if (tmp && tmp->refcnt == node->refcnt + inc)
+ node = merge_ranges(node, tmp);
+ }
+ return node;
+}
+
static int ibv_madvise_range(void *base, size_t size, int advice)
{
uintptr_t start, end;
@@ -464,46 +507,18 @@ static int ibv_madvise_range(void *base, size_t size, int advice)
pthread_mutex_lock(&mm_mutex);
- node = __mm_find_start(start, end);
-
- if (node->start < start) {
- tmp = malloc(sizeof *tmp);
- if (!tmp) {
- ret = -1;
- goto out;
- }
-
- tmp->start = start;
- tmp->end = node->end;
- tmp->refcnt = node->refcnt;
- node->end = start - 1;
-
- __mm_add(tmp);
- node = tmp;
- } else {
- tmp = __mm_prev(node);
- if (tmp && tmp->refcnt == node->refcnt + inc) {
- tmp->end = node->end;
- tmp->refcnt = node->refcnt;
- __mm_remove(node);
- node = tmp;
- }
+ node = get_start_node(start, end, inc);
+ if (!node) {
+ ret = -1;
+ goto out;
}
while (node && node->start <= end) {
if (node->end > end) {
- tmp = malloc(sizeof *tmp);
- if (!tmp) {
+ if (!split_range(node, end + 1)) {
ret = -1;
goto out;
}
-
- tmp->start = end + 1;
- tmp->end = node->end;
- tmp->refcnt = node->refcnt;
- node->end = end;
-
- __mm_add(tmp);
}
node->refcnt += inc;
@@ -537,10 +552,8 @@ static int ibv_madvise_range(void *base, size_t size, int advice)
if (node) {
tmp = __mm_prev(node);
- if (tmp && node->refcnt == tmp->refcnt) {
- tmp->end = node->end;
- __mm_remove(node);
- }
+ if (tmp && node->refcnt == tmp->refcnt)
+ node = merge_ranges(node, tmp);
}
out: