]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
xen: introduce rangeset_claim_range
authorWei Liu <wei.liu2@citrix.com>
Wed, 3 Jan 2018 16:38:54 +0000 (16:38 +0000)
committerRoger Pau Monne <roger.pau@citrix.com>
Thu, 11 Jan 2018 17:51:19 +0000 (17:51 +0000)
Reserve a hole in a rangeset.

Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
Changes since v1:
 - Change function name.
 - Use a local variable instead of *s.
 - Add unlikely to the !prev case.
 - Move the function prototype position in the header file.

xen/common/rangeset.c
xen/include/xen/rangeset.h

index 6c6293c15cd8fd913ac7d9876d3b764c46b5f961..ade34f6a50339995d5fe635a6d10e78dcb9dd8bb 100644 (file)
@@ -298,6 +298,58 @@ int rangeset_report_ranges(
     return rc;
 }
 
+int rangeset_claim_range(struct rangeset *r, unsigned long size,
+                         unsigned long *s)
+{
+    struct range *prev, *next;
+    unsigned long start = 0;
+
+    write_lock(&r->lock);
+
+    for ( prev = NULL, next = first_range(r);
+          next;
+          prev = next, next = next_range(r, next) )
+    {
+        if ( (next->s - start) >= size )
+            goto insert;
+
+        if ( next->e == ~0UL )
+            goto out;
+
+        start = next->e + 1;
+    }
+
+    if ( (~0UL - start) + 1 >= size )
+        goto insert;
+
+ out:
+    write_unlock(&r->lock);
+    return -ENOSPC;
+
+ insert:
+    if ( unlikely(!prev) )
+    {
+        next = alloc_range(r);
+        if ( !next )
+        {
+            write_unlock(&r->lock);
+            return -ENOMEM;
+        }
+
+        next->s = start;
+        next->e = start + size - 1;
+        insert_range(r, prev, next);
+    }
+    else
+        prev->e += size;
+
+    write_unlock(&r->lock);
+
+    *s = start;
+
+    return 0;
+}
+
 int rangeset_add_singleton(
     struct rangeset *r, unsigned long s)
 {
index aa6408248b079f2e7a93db555e998e06635bd91b..1f83b1f44b9e007bba0e4444583b63521e090d04 100644 (file)
@@ -55,9 +55,11 @@ void rangeset_limit(
 bool_t __must_check rangeset_is_empty(
     const struct rangeset *r);
 
-/* Add/remove/query a numeric range. */
+/* Add/claim/remove/query a numeric range. */
 int __must_check rangeset_add_range(
     struct rangeset *r, unsigned long s, unsigned long e);
+int __must_check rangeset_claim_range(struct rangeset *r, unsigned long size,
+                                      unsigned long *s);
 int __must_check rangeset_remove_range(
     struct rangeset *r, unsigned long s, unsigned long e);
 bool_t __must_check rangeset_contains_range(