From 491817c00c456e4331db3ab7e98fd3c30dbf9908 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 7 Jan 2014 18:27:04 +0100 Subject: [PATCH] base: add flex page iterator Issue #8 --- base/include/base/flex_iterator.h | 113 ++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 base/include/base/flex_iterator.h diff --git a/base/include/base/flex_iterator.h b/base/include/base/flex_iterator.h new file mode 100644 index 0000000000..339e163908 --- /dev/null +++ b/base/include/base/flex_iterator.h @@ -0,0 +1,113 @@ +/* + * \brief Flexpage iterator + * \author Alexander Boettcher + * \date 2013-01-07 + */ + +/* + * Copyright (C) 2013-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__BASE__FLEX_ITERATOR_H +#define _INCLUDE__BASE__FLEX_ITERATOR_H + +#include +#include + +namespace Genode { + + class Flexpage + { + public: + + addr_t addr; + addr_t hotspot; + size_t log2_order; + + Flexpage() : addr(~0UL), hotspot(0), log2_order(0) { } + + Flexpage(addr_t a, addr_t h, size_t o) + : addr(a), hotspot(h), log2_order(o) { } + + bool valid() { return addr != ~0UL; } + }; + + + class Flexpage_iterator { + + private: + + addr_t _src_start, _src_size; + addr_t _dst_start, _dst_size; + addr_t _hotspot, _offset; + + /** + * Find least significant set bit in value + */ + inline addr_t + lsb_bit(addr_t const scan) + { + if (scan == 0) + return ~0UL; + return __builtin_ctzl(scan); + } + + public: + + Flexpage_iterator() { } + + Flexpage_iterator(addr_t src_start, size_t src_size, + addr_t dst_start, size_t dst_size, + addr_t hotspot) : + _src_start(src_start), _src_size(src_size), + _dst_start(dst_start), _dst_size(dst_size), + _hotspot(hotspot), _offset(0) + { } + + Flexpage page() + { + size_t const size = min (_src_size, _dst_size); + + addr_t const from_end = _src_start + size; + addr_t const to_end = _dst_start + size; + + if (_offset >= size) + return Flexpage(); + + addr_t const from_curr = _src_start + _offset; + addr_t const to_curr = _dst_start + _offset; + + /* + * The common alignment corresponds to the number of least + * significant zero bits in both addresses. + */ + addr_t const common_bits = from_curr | to_curr; + + /* find least set bit in common bits */ + size_t order = lsb_bit(common_bits); + size_t max = (order == ~0UL) ? ~0UL : (1UL << order); + + /* look if it still fits into both 'src' and 'dst' ranges */ + if ((from_end - from_curr) < max) { + order = log2(from_end - from_curr); + order = (order == ~0UL) ? 12 : order; + max = 1UL << order; + } + + if ((to_end - to_curr) < max) { + order = log2(to_end - to_curr); + order = (order == ~0UL) ? 12 : order; + } + + /* advance offset by current flexpage size */ + _offset += (1UL << order); + + return Flexpage(from_curr, _hotspot + _offset - (1UL << order), order); + } + }; + +} +#endif /* _INCLUDE__BASE__FLEX_ITERATOR_H */