[bitmap] Add reverse scanning

This CL adds RScan and RFind to complement Scan and Find, respectively.
The functions find the last occurences of a non-matching bit or run of
matching bits, instead of the first.

The interface for Scan and Find has also slightly changed: while
returning "bitmax" made some sense on failure before, returning "bitoff"
doesn't for the reverse versions since it would be a valid offset.
Returning "bitoff-1" is similarly problematic, as bitoff may be 0.
Instead, Scan now returns a bool, and Find does not set "out" in their
respective failure cases.

ZX-1781 #comment Fixed

Change-Id: Ied08f8c74bca17e7b537d16075a2005e00d536fc
diff --git a/kernel/lib/hypervisor/include/hypervisor/interrupt_tracker.h b/kernel/lib/hypervisor/include/hypervisor/interrupt_tracker.h
index c0d6caf..c10139f 100644
--- a/kernel/lib/hypervisor/include/hypervisor/interrupt_tracker.h
+++ b/kernel/lib/hypervisor/include/hypervisor/interrupt_tracker.h
@@ -26,7 +26,7 @@
     // Returns whether there are pending interrupts.
     bool Pending() {
         AutoSpinLock lock(&lock_);
-        return bitmap_.Scan(0, N, false) != N;
+        return !bitmap_.Scan(0, N, false);
     }
 
     bool TryPop(uint32_t vector) {
@@ -40,16 +40,15 @@
 
     // Pops the highest priority interrupt.
     zx_status_t Pop(uint32_t* vector) {
-        uint32_t value;
+        size_t value;
         {
             AutoSpinLock lock(&lock_);
-            value = static_cast<uint32_t>(bitmap_.Scan(0, N, false));
-            if (value == N) {
+            if (bitmap_.Scan(0, N, false, &value)) {
                 return ZX_ERR_NOT_FOUND;
             }
             bitmap_.ClearOne(value);
         }
-        *vector = reverse(value);
+        *vector = reverse(static_cast<uint32_t>(value));
         return ZX_OK;
     }
 
diff --git a/system/ulib/bitmap/include/bitmap/raw-bitmap.h b/system/ulib/bitmap/include/bitmap/raw-bitmap.h
index 2aac169..4e10bfa 100644
--- a/system/ulib/bitmap/include/bitmap/raw-bitmap.h
+++ b/system/ulib/bitmap/include/bitmap/raw-bitmap.h
@@ -11,11 +11,11 @@
 #include <stdint.h>
 #include <string.h>
 
-#include <zircon/assert.h>
-#include <zircon/types.h>
 #include <fbl/algorithm.h>
 #include <fbl/macros.h>
 #include <fbl/type_support.h>
+#include <zircon/assert.h>
+#include <zircon/types.h>
 
 namespace bitmap {
 namespace internal {
@@ -45,15 +45,24 @@
     // restrict access to a smaller portion of the bitmap (via Shrink).
     zx_status_t Shrink(size_t size);
 
-    // Returns the lesser of bitmax and the index of the first bit that doesn't
-    // match *is_set* starting from *bitoff*.
-    size_t Scan(size_t bitoff, size_t bitmax, bool is_set) const;
+    // Returns true if all bits in the range [*bitoff*, *bitmax*) match
+    // *is_set*, otherwise returns false and sets *out* (if provided) to the
+    // first (or last, in the case of ReverseScan) bit that doesn't match. An
+    // empty region (i.e. *bitoff* is greater than *bitmax*, or *bitoff* is
+    // outside the range of the bitmap) will return true.
+    bool Scan(size_t bitoff, size_t bitmax, bool is_set,
+              size_t* out = nullptr) const;
+    bool ReverseScan(size_t bitoff, size_t bitmax, bool is_set,
+                     size_t* out = nullptr) const;
 
-    // Find a run of *run_len* *is_set* bits, between bitoff and bitmax.
-    // Returns the start of the run in *out*, or bitmax if it is
-    // not found in the provided range.
-    // If the run is not found, "ZX_ERR_NO_RESOURCES" is returned.
-    zx_status_t Find(bool is_set, size_t bitoff, size_t bitmax, size_t run_len, size_t* out) const;
+    // Finds the first (or last, in the case of ReverseFind) run of *run_len*
+    // *is_set* bits, in [*bitoff*, *bitmax*). Returns the start of the run in
+    // *out* and returns ZX_OK if a run is found, otherwise returns
+    // ZX_ERR_NO_RESOURCES.
+    zx_status_t Find(bool is_set, size_t bitoff, size_t bitmax, size_t run_len,
+                     size_t* out) const;
+    zx_status_t ReverseFind(bool is_set, size_t bitoff, size_t bitmax,
+                            size_t run_len, size_t* out) const;
 
     // Returns true if all the bits in [*bitoff*, *bitmax*) are set. Afterwards,
     // *first_unset* will be set to the lesser of bitmax and the index of the
@@ -86,7 +95,8 @@
 //   - void* GetData()
 //      To access the underlying storage.
 //   - zx_status_t Grow(size_t size)
-//      (optional) To expand the underlying storage to fit at least |size| bytes.
+//      (optional) To expand the underlying storage to fit at least |size|
+//      bytes.
 template <typename Storage>
 class RawBitmapGeneric final : public RawBitmapBase {
 public:
@@ -116,8 +126,10 @@
         }
 
         // Clear all the "newly grown" bytes
-        uintptr_t addr = reinterpret_cast<uintptr_t>(bits_.GetData()) + old_len * sizeof(size_t);
-        memset(reinterpret_cast<void*>(addr), 0, (new_len - old_len) * sizeof(size_t));
+        uintptr_t addr = reinterpret_cast<uintptr_t>(bits_.GetData()) +
+                         old_len * sizeof(size_t);
+        memset(reinterpret_cast<void*>(addr), 0,
+               (new_len - old_len) * sizeof(size_t));
 
         size_t old_size = size_;
         data_ = static_cast<size_t*>(bits_.GetData());
diff --git a/system/ulib/bitmap/raw-bitmap.cpp b/system/ulib/bitmap/raw-bitmap.cpp
index d66646d..6c7b724 100644
--- a/system/ulib/bitmap/raw-bitmap.cpp
+++ b/system/ulib/bitmap/raw-bitmap.cpp
@@ -8,18 +8,19 @@
 #include <limits.h>
 #include <stddef.h>
 
-#include <zircon/types.h>
 #include <fbl/algorithm.h>
 #include <fbl/macros.h>
+#include <zircon/types.h>
 
+namespace bitmap {
 namespace {
 
 // Translates a bit offset into a starting index in the bitmap array.
 constexpr size_t FirstIdx(size_t bitoff) {
-    return bitoff / bitmap::kBits;
+    return bitoff / kBits;
 }
 
-// GetMask returns a 64-bit bitmask.  If the block of the bitmap we're looking
+// GetMask returns a 64-bit bitmask. If the block of the bitmap we're looking
 // at isn't the first or last, all bits are set.  Otherwise, the bits outside of
 // [off,max) are cleared.  Bits are counted with the LSB as 0 and the MSB as 63.
 //
@@ -29,38 +30,51 @@
 //  GetMask(false,  true, 16, 48) => 0x0000ffffffffffff
 //  GetMask(true,   true, 16, 48) => 0x0000ffffffff0000
 size_t GetMask(bool first, bool last, size_t off, size_t max) {
-    size_t ones = 0;
-    ones = ~ones;
+    size_t ones = ~(size_t(0));
     size_t mask = ones;
     if (first) {
-        mask &= ones << (off % bitmap::kBits);
+        mask &= ones << (off % kBits);
     }
     if (last) {
-        mask &= ones >> ((bitmap::kBits - (max % bitmap::kBits)) % bitmap::kBits);
+        mask &= ones >> ((kBits - (max % kBits)) % kBits);
     }
     return mask;
 }
 
+// Applies a bitmask to the given data value. The result value has bits set
+// which fall within the mask but do not match is_set.
+size_t MaskBits(size_t data, size_t idx, size_t bitoff, size_t bitmax,
+                bool is_set) {
+    size_t mask = GetMask(idx == FirstIdx(bitoff), idx == LastIdx(bitmax),
+                          bitoff, bitmax);
+    if (is_set) {
+        // If is_set=true, invert the mask, OR it with the value, and invert
+        // it again to hopefully get all zeros.
+        return ~(~mask | data);
+    } else {
+        // If is_set=false, just AND the mask with the value to hopefully
+        // get all zeros.
+        return mask & data;
+    }
+}
+
 // Counts the number of zeros.  It assumes everything in the array up to
 // bits_[idx] is zero.
 #if (SIZE_MAX == UINT_MAX)
-#define CTZ(x) (x == 0 ? bitmap::kBits : __builtin_ctz(x))
+#define CLZ(x) (x == 0 ? kBits : __builtin_clz(x))
+#define CTZ(x) (x == 0 ? kBits : __builtin_ctz(x))
 #elif (SIZE_MAX == ULONG_MAX)
-#define CTZ(x) (x == 0 ? bitmap::kBits : __builtin_ctzl(x))
+#define CLZ(x) (x == 0 ? kBits : __builtin_clzl(x))
+#define CTZ(x) (x == 0 ? kBits : __builtin_ctzl(x))
 #elif (SIZE_MAX == ULLONG_MAX)
-#define CTZ(x) (x == 0 ? bitmap::kBits : __builtin_ctzll(x))
+#define CLZ(x) (x == 0 ? kBits : __builtin_clzll(x))
+#define CTZ(x) (x == 0 ? kBits : __builtin_ctzll(x))
 #else
 #error "Unsupported size_t length"
 #endif
-size_t CountZeros(size_t idx, size_t value) {
-    return idx * bitmap::kBits + CTZ(value);
-}
-#undef CTZ
 
 } // namespace
 
-namespace bitmap {
-
 zx_status_t RawBitmapBase::Shrink(size_t size) {
     if (size > size_) {
         return ZX_ERR_NO_MEMORY;
@@ -69,58 +83,96 @@
     return ZX_OK;
 }
 
-size_t RawBitmapBase::Scan(size_t bitoff, size_t bitmax, bool is_set) const {
+bool RawBitmapBase::Scan(size_t bitoff, size_t bitmax, bool is_set,
+                         size_t* out) const {
     bitmax = fbl::min(bitmax, size_);
     if (bitoff >= bitmax) {
-        return bitmax;
+        return true;
     }
-    size_t first_idx = FirstIdx(bitoff);
-    size_t last_idx = LastIdx(bitmax);
-    size_t i = first_idx;
-    size_t value = 0;
-    for (i = first_idx; i <= last_idx; ++i) {
-        value = GetMask(i == first_idx, i == last_idx, bitoff, bitmax);
-        if (is_set) {
-            // If is_set=true, invert the mask, OR it with the value, and invert
-            // it again to hopefully get all zeros.
-            value = ~(~value | data_[i]);
-        } else {
-            // If is_set=false, just AND the mask with the value to hopefully
-            // get all zeros.
-            value &= data_[i];
+    size_t i = FirstIdx(bitoff);
+    while (true) {
+        size_t masked = MaskBits(data_[i], i, bitoff, bitmax, is_set);
+        if (masked != 0) {
+            if (out) {
+                *out = i * bitmap::kBits + CTZ(masked);
+            }
+            return false;
         }
-        if (value != 0) {
-            break;
+        if (i == LastIdx(bitmax)) {
+            return true;
         }
+        ++i;
     }
-    return fbl::min(bitmax, CountZeros(i, value));
+}
+
+bool RawBitmapBase::ReverseScan(size_t bitoff, size_t bitmax, bool is_set,
+                          size_t* out) const {
+    bitmax = fbl::min(bitmax, size_);
+    if (bitoff >= bitmax) {
+        return true;
+    }
+    size_t i = LastIdx(bitmax);
+    while (true) {
+        size_t masked = MaskBits(data_[i], i, bitoff, bitmax, is_set);
+        if (masked != 0) {
+            if (out) {
+                *out = (i + 1) * bitmap::kBits - (CLZ(masked) + 1);
+            }
+            return false;
+        }
+        if (i == FirstIdx(bitoff)) {
+            return true;
+        }
+        --i;
+    }
 }
 
 zx_status_t RawBitmapBase::Find(bool is_set, size_t bitoff, size_t bitmax,
-                                                size_t run_len, size_t* out) const {
+                                size_t run_len, size_t* out) const {
     if (!out || bitmax <= bitoff) {
         return ZX_ERR_INVALID_ARGS;
     }
     size_t start = bitoff;
-    while (bitoff - start < run_len && bitoff < bitmax) {
-        start = Scan(bitoff, bitmax, !is_set);
-        if (bitmax - start < run_len) {
-            *out = bitmax;
+    while (true) {
+        if (Scan(bitoff, bitmax, !is_set, &start) ||
+            (bitmax - start < run_len)) {
             return ZX_ERR_NO_RESOURCES;
         }
-        bitoff = Scan(start, start + run_len, is_set);
+        if (Scan(start, start + run_len, is_set, &bitoff)) {
+            *out = start;
+            return ZX_OK;
+        }
     }
-    *out = start;
-    return ZX_OK;
+}
+
+zx_status_t RawBitmapBase::ReverseFind(bool is_set, size_t bitoff, size_t bitmax,
+                                 size_t run_len, size_t* out) const {
+    if (!out || bitmax <= bitoff) {
+        return ZX_ERR_INVALID_ARGS;
+    }
+    size_t start = bitmax;
+    while (true) {
+        if (ReverseScan(bitoff, bitmax, !is_set, &start)) {
+            return ZX_ERR_NO_RESOURCES;
+        }
+        // Increment start to be last bit that is !is_set
+        ++start;
+        if ((start - bitoff < run_len)) {
+            return ZX_ERR_NO_RESOURCES;
+        }
+        if (ReverseScan(start - run_len, start, is_set, &bitmax)) {
+            *out = start - run_len;
+            return ZX_OK;
+        }
+    }
 }
 
 bool RawBitmapBase::Get(size_t bitoff, size_t bitmax, size_t* first) const {
-    bitmax = fbl::min(bitmax, size_);
-    size_t result = Scan(bitoff, bitmax, true);
-    if (first) {
-        *first = result;
+    bool result;
+    if ((result = Scan(bitoff, bitmax, true, first)) && first) {
+        *first = bitmax;
     }
-    return result == bitmax;
+    return result;
 }
 
 zx_status_t RawBitmapBase::Set(size_t bitoff, size_t bitmax) {
@@ -133,8 +185,7 @@
     size_t first_idx = FirstIdx(bitoff);
     size_t last_idx = LastIdx(bitmax);
     for (size_t i = first_idx; i <= last_idx; ++i) {
-        data_[i] |=
-                GetMask(i == first_idx, i == last_idx, bitoff, bitmax);
+        data_[i] |= GetMask(i == first_idx, i == last_idx, bitoff, bitmax);
     }
     return ZX_OK;
 }
@@ -149,8 +200,7 @@
     size_t first_idx = FirstIdx(bitoff);
     size_t last_idx = LastIdx(bitmax);
     for (size_t i = first_idx; i <= last_idx; ++i) {
-        data_[i] &=
-                ~(GetMask(i == first_idx, i == last_idx, bitoff, bitmax));
+        data_[i] &= ~(GetMask(i == first_idx, i == last_idx, bitoff, bitmax));
     }
     return ZX_OK;
 }
diff --git a/system/utest/bitmap/raw-bitmap-tests.cpp b/system/utest/bitmap/raw-bitmap-tests.cpp
index bd5b01b..c540ae8 100644
--- a/system/utest/bitmap/raw-bitmap-tests.cpp
+++ b/system/utest/bitmap/raw-bitmap-tests.cpp
@@ -12,8 +12,7 @@
 namespace bitmap {
 namespace tests {
 
-template <typename RawBitmap>
-static bool InitializedEmpty(void) {
+template <typename RawBitmap> static bool InitializedEmpty(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -32,8 +31,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool SingleBit(void) {
+template <typename RawBitmap> static bool SingleBit(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -51,8 +49,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool SetTwice(void) {
+template <typename RawBitmap> static bool SetTwice(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -68,8 +65,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool ClearTwice(void) {
+template <typename RawBitmap> static bool ClearTwice(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -87,8 +83,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool GetReturnArg(void) {
+template <typename RawBitmap> static bool GetReturnArg(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -115,8 +110,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool SetRange(void) {
+template <typename RawBitmap> static bool SetRange(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -144,18 +138,36 @@
     EXPECT_TRUE(bitmap.Get(50, 80, &first_unset), "get part of range");
     EXPECT_EQ(first_unset, 80U, "check returned arg");
 
-    EXPECT_EQ(bitmap.Scan(0, 100, true), 0U, "scan set bits out of range");
-    EXPECT_EQ(bitmap.Scan(0, 100, false), 2U, "scan cleared bits to start");
-    EXPECT_EQ(bitmap.Scan(2, 100, true), 100U, "scan set bits to end");
-    EXPECT_EQ(bitmap.Scan(2, 100, false), 2U, "scan cleared bits in set range");
-    EXPECT_EQ(bitmap.Scan(50, 80, true), 80U, "scan set bits in subrange");
-    EXPECT_EQ(bitmap.Scan(100, 200, false), 128U, "scan past end of bitmap");
+    size_t result;
+    EXPECT_FALSE(bitmap.Scan(0, 100, true, &result), "scan set bits");
+    EXPECT_EQ(result, 0U, "scan set bits");
+    EXPECT_FALSE(bitmap.ReverseScan(0, 100, true, &result), "reverse scan set bits");
+    EXPECT_EQ(result, 1U, "reverse scan set bits");
+
+    EXPECT_FALSE(bitmap.Scan(0, 100, false, &result), "scan cleared bits");
+    EXPECT_EQ(result, 2U, "scan cleared bits to start");
+    EXPECT_FALSE(bitmap.ReverseScan(0, 100, false, &result), "reverse scan cleared bits");
+    EXPECT_EQ(result, 99U, "reverse scan cleared bits");
+
+    EXPECT_TRUE(bitmap.Scan(2, 100, true), "scan set bits in set range");
+    EXPECT_TRUE(bitmap.ReverseScan(2, 100, true), "reverse scan set bits in set range");
+
+    EXPECT_FALSE(bitmap.Scan(2, 100, false, &result), "scan cleared bits in set range");
+    EXPECT_EQ(result, 2U, "scan cleared bits in set range");
+    EXPECT_FALSE(bitmap.ReverseScan(2, 100, false, &result),
+                 "reverse scan cleared bits in set range");
+    EXPECT_EQ(result, 99U, "reverse scan cleared bits in set range");
+
+    EXPECT_TRUE(bitmap.Scan(50, 80, true), "scan set bits in subrange");
+    EXPECT_TRUE(bitmap.ReverseScan(50, 80, true), "reverse scan set bits in subrange");
+
+    EXPECT_TRUE(bitmap.Scan(100, 200, false), "scan past end of bitmap");
+    EXPECT_TRUE(bitmap.ReverseScan(100, 200, false), "reverse scan past end of bitmap");
 
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool FindSimple(void) {
+template <typename RawBitmap> static bool FindSimple(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -166,87 +178,159 @@
 
     // Invalid finds
     EXPECT_EQ(bitmap.Find(false, 0, 0, 1, &bitoff_start), ZX_ERR_INVALID_ARGS, "bad range");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 0, 1, &bitoff_start), ZX_ERR_INVALID_ARGS, "bad range");
     EXPECT_EQ(bitmap.Find(false, 1, 0, 1, &bitoff_start), ZX_ERR_INVALID_ARGS, "bad range");
+    EXPECT_EQ(bitmap.ReverseFind(false, 1, 0, 1, &bitoff_start), ZX_ERR_INVALID_ARGS, "bad range");
     EXPECT_EQ(bitmap.Find(false, 0, 1, 1, nullptr), ZX_ERR_INVALID_ARGS, "bad output");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 1, 1, nullptr), ZX_ERR_INVALID_ARGS, "bad output");
 
     // Finds from offset zero
     EXPECT_EQ(bitmap.Find(false, 0, 100, 1, &bitoff_start), ZX_OK, "find unset");
     EXPECT_EQ(bitoff_start, 0, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 100, 1, &bitoff_start), ZX_OK, "reverse find unset");
+    EXPECT_EQ(bitoff_start, 99, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(true, 0, 100, 1, &bitoff_start), ZX_ERR_NO_RESOURCES, "find set");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(true, 0, 100, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse find set");
+
     EXPECT_EQ(bitmap.Find(false, 0, 100, 5, &bitoff_start), ZX_OK, "find more unset");
     EXPECT_EQ(bitoff_start, 0, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 100, 5, &bitoff_start), ZX_OK,
+              "reverse find more unset");
+    EXPECT_EQ(bitoff_start, 95, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(true, 0, 100, 5, &bitoff_start), ZX_ERR_NO_RESOURCES, "find more set");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
-    EXPECT_EQ(bitmap.Find(false, 0, 100, 100, &bitoff_start), ZX_OK, "find all uset");
+    EXPECT_EQ(bitmap.ReverseFind(true, 0, 100, 5, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse find more set");
+
+    EXPECT_EQ(bitmap.Find(false, 0, 100, 100, &bitoff_start), ZX_OK, "find all unset");
     EXPECT_EQ(bitoff_start, 0, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 100, 100, &bitoff_start), ZX_OK,
+              "reverse find all unset");
+    EXPECT_EQ(bitoff_start, 0, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(true, 0, 100, 100, &bitoff_start), ZX_ERR_NO_RESOURCES, "find all set");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(true, 0, 100, 100, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse find all set");
 
     // Finds at an offset
     EXPECT_EQ(bitmap.Find(false, 50, 100, 3, &bitoff_start), ZX_OK, "find at offset");
     EXPECT_EQ(bitoff_start, 50, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 50, 100, 3, &bitoff_start), ZX_OK,
+              "reverse find at offset");
+    EXPECT_EQ(bitoff_start, 97, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(true, 50, 100, 3, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail at offset");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(true, 50, 100, 3, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail at offset");
+
     EXPECT_EQ(bitmap.Find(false, 90, 100, 10, &bitoff_start), ZX_OK, "find at offset end");
     EXPECT_EQ(bitoff_start, 90, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 90, 100, 10, &bitoff_start), ZX_OK,
+              "reverse find at offset end");
+    EXPECT_EQ(bitoff_start, 90, "check returned arg");
 
     // Invalid scans
     EXPECT_EQ(bitmap.Find(false, 0, 100, 101, &bitoff_start), ZX_ERR_NO_RESOURCES, "no space");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 100, 101, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "no space");
     EXPECT_EQ(bitmap.Find(false, 91, 100, 10, &bitoff_start), ZX_ERR_NO_RESOURCES, "no space");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 91, 100, 10, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "no space");
     EXPECT_EQ(bitmap.Find(false, 90, 100, 11, &bitoff_start), ZX_ERR_NO_RESOURCES, "no space");
-    EXPECT_EQ(bitoff_start, 100, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 90, 100, 11, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "no space");
     EXPECT_EQ(bitmap.Find(false, 90, 95, 6, &bitoff_start), ZX_ERR_NO_RESOURCES, "no space");
-    EXPECT_EQ(bitoff_start, 95, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 90, 95, 6, &bitoff_start), ZX_ERR_NO_RESOURCES, "no space");
 
     // Fill the bitmap
     EXPECT_EQ(bitmap.Set(5, 10), ZX_OK, "set range");
     EXPECT_EQ(bitmap.Set(20, 30), ZX_OK, "set range");
     EXPECT_EQ(bitmap.Set(32, 35), ZX_OK, "set range");
+    EXPECT_EQ(bitmap.Set(90, 95), ZX_OK, "set range");
+    EXPECT_EQ(bitmap.Set(70, 80), ZX_OK, "set range");
+    EXPECT_EQ(bitmap.Set(65, 68), ZX_OK, "set range");
 
     EXPECT_EQ(bitmap.Find(false, 0, 50, 5, &bitoff_start), ZX_OK, "find in first group");
     EXPECT_EQ(bitoff_start, 0, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 50, 100, 5, &bitoff_start), ZX_OK,
+              "reverse find in first group");
+    EXPECT_EQ(bitoff_start, 95, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(false, 0, 50, 10, &bitoff_start), ZX_OK, "find in second group");
     EXPECT_EQ(bitoff_start, 10, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 50, 100, 10, &bitoff_start), ZX_OK,
+              "reverse find in second group");
+    EXPECT_EQ(bitoff_start, 80, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(false, 0, 50, 15, &bitoff_start), ZX_OK, "find in third group");
     EXPECT_EQ(bitoff_start, 35, "check returned arg");
-    EXPECT_EQ(bitmap.Find(false, 0, 50, 16, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find");
+    EXPECT_EQ(bitmap.ReverseFind(false, 50, 100, 15, &bitoff_start), ZX_OK,
+              "reverse find in third group");
     EXPECT_EQ(bitoff_start, 50, "check returned arg");
 
+    EXPECT_EQ(bitmap.Find(false, 0, 50, 16, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find");
+    EXPECT_EQ(bitmap.ReverseFind(false, 50, 100, 16, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find");
+
     EXPECT_EQ(bitmap.Find(false, 5, 20, 10, &bitoff_start), ZX_OK, "find space (offset)");
     EXPECT_EQ(bitoff_start, 10, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 80, 95, 10, &bitoff_start), ZX_OK,
+              "reverse find space (offset)");
+    EXPECT_EQ(bitoff_start, 80, "check returned arg");
+
     EXPECT_EQ(bitmap.Find(false, 5, 25, 10, &bitoff_start), ZX_OK, "find space (offset)");
     EXPECT_EQ(bitoff_start, 10, "check returned arg");
-    EXPECT_EQ(bitmap.Find(false, 5, 15, 6, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find (offset)");
-    EXPECT_EQ(bitoff_start, 15, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 75, 95, 10, &bitoff_start), ZX_OK,
+              "reverse find space (offset)");
+    EXPECT_EQ(bitoff_start, 80, "check returned arg");
+
+    EXPECT_EQ(bitmap.Find(false, 5, 15, 6, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "fail to find (offset)");
+    EXPECT_EQ(bitmap.ReverseFind(false, 85, 95, 6, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find (offset)");
 
     EXPECT_EQ(bitmap.Find(true, 0, 15, 2, &bitoff_start), ZX_OK, "find set bits");
     EXPECT_EQ(bitoff_start, 5, "check returned arg");
-    EXPECT_EQ(bitmap.Find(true, 0, 15, 6, &bitoff_start), ZX_ERR_NO_RESOURCES, "find set bits (fail)");
-    EXPECT_EQ(bitoff_start, 15, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(true, 85, 100, 2, &bitoff_start), ZX_OK, "reverse find set bits");
+    EXPECT_EQ(bitoff_start, 93, "check returned arg");
+
+    EXPECT_EQ(bitmap.Find(true, 0, 15, 6, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "find set bits (fail)");
+    EXPECT_EQ(bitmap.ReverseFind(true, 85, 100, 6, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse find set bits (fail)");
 
     EXPECT_EQ(bitmap.Find(false, 32, 35, 3, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find");
-    EXPECT_EQ(bitoff_start, 35, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 65, 68, 3, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find");
+
     EXPECT_EQ(bitmap.Find(false, 32, 35, 4, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find");
-    EXPECT_EQ(bitoff_start, 35, "check returned arg");
-    EXPECT_EQ(bitmap.Find(true, 32, 35, 4, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find (set)");
-    EXPECT_EQ(bitoff_start, 35, "check returned arg");
+    EXPECT_EQ(bitmap.ReverseFind(false, 65, 68, 4, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find");
+
+    EXPECT_EQ(bitmap.Find(true, 32, 35, 4, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "fail to find (set)");
+    EXPECT_EQ(bitmap.ReverseFind(true, 65, 68, 4, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find (set)");
 
     // Fill the whole bitmap
     EXPECT_EQ(bitmap.Set(0, 128), ZX_OK, "set range");
 
-    EXPECT_EQ(bitmap.Find(false, 0, 1, 1, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find (small)");
-    EXPECT_EQ(bitoff_start, 1, "check returned arg");
-    EXPECT_EQ(bitmap.Find(false, 0, 128, 1, &bitoff_start), ZX_ERR_NO_RESOURCES, "fail to find (large)");
-    EXPECT_EQ(bitoff_start, 128, "check returned arg");
+    EXPECT_EQ(bitmap.Find(false, 0, 1, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "fail to find (small)");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 1, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find (small)");
+
+    EXPECT_EQ(bitmap.Find(false, 0, 128, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "fail to find (large)");
+    EXPECT_EQ(bitmap.ReverseFind(false, 0, 128, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "reverse fail to find (large)");
 
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool ClearAll(void) {
+template <typename RawBitmap> static bool ClearAll(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -268,8 +352,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool ClearSubrange(void) {
+template <typename RawBitmap> static bool ClearSubrange(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -296,8 +379,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool BoundaryArguments(void) {
+template <typename RawBitmap> static bool BoundaryArguments(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -319,8 +401,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool SetOutOfOrder(void) {
+template <typename RawBitmap> static bool SetOutOfOrder(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -335,8 +416,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool GrowAcrossPage(void) {
+template <typename RawBitmap> static bool GrowAcrossPage(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -355,8 +435,8 @@
     EXPECT_NE(bitmap.SetOne(16 * PAGE_SIZE - 1), ZX_OK);
 
     EXPECT_EQ(bitmap.Grow(16 * PAGE_SIZE), ZX_OK);
-    EXPECT_EQ(bitmap.Find(true, 101, 16 * PAGE_SIZE, 1, &bitoff_start),
-              ZX_ERR_NO_RESOURCES, "Expected tail end of bitmap to be unset");
+    EXPECT_EQ(bitmap.Find(true, 101, 16 * PAGE_SIZE, 1, &bitoff_start), ZX_ERR_NO_RESOURCES,
+              "Expected tail end of bitmap to be unset");
 
     // Now we can set the previously inaccessible bits
     EXPECT_FALSE(bitmap.GetOne(16 * PAGE_SIZE - 1));
@@ -376,8 +456,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool GrowShrink(void) {
+template <typename RawBitmap> static bool GrowShrink(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -415,10 +494,9 @@
                             "Expected bit outside shrink range to be set");
 
                 size_t bitoff_start;
-                EXPECT_EQ(bitmap.Find(true, bitmap_size - shrink_len,
-                                      bitmap_size, 1, &bitoff_start),
-                          ZX_ERR_NO_RESOURCES,
-                          "Expected tail end of bitmap to be unset");
+                EXPECT_EQ(
+                    bitmap.Find(true, bitmap_size - shrink_len, bitmap_size, 1, &bitoff_start),
+                    ZX_ERR_NO_RESOURCES, "Expected tail end of bitmap to be unset");
             }
         }
     }
@@ -426,8 +504,7 @@
     END_TEST;
 }
 
-template <typename RawBitmap>
-static bool GrowFailure(void) {
+template <typename RawBitmap> static bool GrowFailure(void) {
     BEGIN_TEST;
 
     RawBitmap bitmap;
@@ -442,17 +519,17 @@
 }
 
 #define RUN_TEMPLATIZED_TEST(test, specialization) RUN_TEST(test<specialization>)
-#define ALL_TESTS(specialization)                           \
-    RUN_TEMPLATIZED_TEST(InitializedEmpty, specialization)  \
-    RUN_TEMPLATIZED_TEST(SingleBit, specialization)         \
-    RUN_TEMPLATIZED_TEST(SetTwice, specialization)          \
-    RUN_TEMPLATIZED_TEST(ClearTwice, specialization)        \
-    RUN_TEMPLATIZED_TEST(GetReturnArg, specialization)      \
-    RUN_TEMPLATIZED_TEST(SetRange, specialization)          \
-    RUN_TEMPLATIZED_TEST(FindSimple, specialization)        \
-    RUN_TEMPLATIZED_TEST(ClearSubrange, specialization)     \
-    RUN_TEMPLATIZED_TEST(BoundaryArguments, specialization) \
-    RUN_TEMPLATIZED_TEST(ClearAll, specialization)          \
+#define ALL_TESTS(specialization)                                                                  \
+    RUN_TEMPLATIZED_TEST(InitializedEmpty, specialization)                                         \
+    RUN_TEMPLATIZED_TEST(SingleBit, specialization)                                                \
+    RUN_TEMPLATIZED_TEST(SetTwice, specialization)                                                 \
+    RUN_TEMPLATIZED_TEST(ClearTwice, specialization)                                               \
+    RUN_TEMPLATIZED_TEST(GetReturnArg, specialization)                                             \
+    RUN_TEMPLATIZED_TEST(SetRange, specialization)                                                 \
+    RUN_TEMPLATIZED_TEST(FindSimple, specialization)                                               \
+    RUN_TEMPLATIZED_TEST(ClearSubrange, specialization)                                            \
+    RUN_TEMPLATIZED_TEST(BoundaryArguments, specialization)                                        \
+    RUN_TEMPLATIZED_TEST(ClearAll, specialization)                                                 \
     RUN_TEMPLATIZED_TEST(SetOutOfOrder, specialization)
 
 BEGIN_TEST_CASE(raw_bitmap_tests)