genode/repos/base/include/util/flex_iterator.h

117 lines
2.5 KiB
C
Raw Normal View History

2014-01-07 17:27:04 +00:00
/*
* \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__UTIL__FLEX_ITERATOR_H_
#define _INCLUDE__UTIL__FLEX_ITERATOR_H_
2014-01-07 17:27:04 +00:00
#include <base/stdint.h>
#include <util/misc_math.h>
namespace Genode {
struct Flexpage;
class Flexpage_iterator;
}
2014-01-07 17:27:04 +00:00
struct Genode::Flexpage
{
addr_t addr;
addr_t hotspot;
size_t log2_order;
2014-01-07 17:27:04 +00:00
Flexpage() : addr(~0UL), hotspot(0), log2_order(0) { }
2014-01-07 17:27:04 +00:00
Flexpage(addr_t a, addr_t h, size_t o)
: addr(a), hotspot(h), log2_order(o) { }
2014-01-07 17:27:04 +00:00
bool valid() { return addr != ~0UL; }
};
2014-01-07 17:27:04 +00:00
class Genode::Flexpage_iterator
{
private:
2014-01-07 17:27:04 +00:00
addr_t _src_start, _src_size;
addr_t _dst_start, _dst_size;
addr_t _hotspot, _offset;
2014-01-07 17:27:04 +00:00
/**
* 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);
}
2014-01-07 17:27:04 +00:00
public:
2014-01-07 17:27:04 +00:00
Flexpage_iterator() { }
2014-01-07 17:27:04 +00:00
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)
{ }
2014-01-07 17:27:04 +00:00
Flexpage page()
{
size_t const size = min (_src_size, _dst_size);
2014-01-07 17:27:04 +00:00
addr_t const from_end = _src_start + size;
addr_t const to_end = _dst_start + size;
2014-01-07 17:27:04 +00:00
if (_offset >= size)
return Flexpage();
2014-01-07 17:27:04 +00:00
addr_t const from_curr = _src_start + _offset;
addr_t const to_curr = _dst_start + _offset;
2014-01-07 17:27:04 +00:00
/*
* The common alignment corresponds to the number of least
* significant zero bits in both addresses.
*/
addr_t const common_bits = from_curr | to_curr;
2014-01-07 17:27:04 +00:00
/* find least set bit in common bits */
size_t order = lsb_bit(common_bits);
size_t max = (order == ~0UL) ? ~0UL : (1UL << order);
2014-01-07 17:27:04 +00:00
/* 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;
}
2014-01-07 17:27:04 +00:00
if ((to_end - to_curr) < max) {
order = log2(to_end - to_curr);
order = (order == ~0UL) ? 12 : order;
}
2014-01-07 17:27:04 +00:00
/* advance offset by current flexpage size */
_offset += (1UL << order);
2014-01-07 17:27:04 +00:00
return Flexpage(from_curr, _hotspot + _offset - (1UL << order), order);
}
};
2014-01-07 17:27:04 +00:00
#endif /* _INCLUDE__UTIL__FLEX_ITERATOR_H_ */