1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/***************************************************************************
* lib/mng/disk_allocator.cpp
*
* Part of the STXXL. See http://stxxl.sourceforge.net
*
* Copyright (C) 2002 Roman Dementiev <dementiev@mpi-sb.mpg.de>
* Copyright (C) 2008, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
**************************************************************************/
#include <stxxl/bits/common/error_handling.h>
#include <stxxl/bits/common/exceptions.h>
#include <stxxl/bits/common/types.h>
#include <stxxl/bits/mng/disk_allocator.h>
#include <stxxl/bits/namespace.h>
#include <stxxl/bits/verbose.h>
#include <cassert>
#include <map>
#include <ostream>
#include <utility>
STXXL_BEGIN_NAMESPACE
void disk_allocator::dump() const
{
int64 total = 0;
sortseq::const_iterator cur = free_space.begin();
STXXL_ERRMSG("Free regions dump:");
for ( ; cur != free_space.end(); ++cur)
{
STXXL_ERRMSG("Free chunk: begin: " << (cur->first) << " size: " << (cur->second));
total += cur->second;
}
STXXL_ERRMSG("Total bytes: " << total);
}
void disk_allocator::deallocation_error(
stxxl::int64 block_pos, stxxl::int64 block_size,
const sortseq::iterator& pred, const sortseq::iterator& succ) const
{
STXXL_ERRMSG("Error deallocating block at " << block_pos << " size " << block_size);
STXXL_ERRMSG(((pred == succ) ? "pred==succ" : "pred!=succ"));
if (pred == free_space.end()) {
STXXL_ERRMSG("pred==free_space.end()");
} else {
if (pred == free_space.begin())
STXXL_ERRMSG("pred==free_space.begin()");
STXXL_ERRMSG("pred: begin=" << pred->first << " size=" << pred->second);
}
if (succ == free_space.end()) {
STXXL_ERRMSG("succ==free_space.end()");
} else {
if (succ == free_space.begin())
STXXL_ERRMSG("succ==free_space.begin()");
STXXL_ERRMSG("succ: begin=" << succ->first << " size=" << succ->second);
}
dump();
}
void disk_allocator::add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size)
{
//assert(block_size);
//dump();
STXXL_VERBOSE2("Deallocating a block with size: " << block_size << " position: " << block_pos);
stxxl::int64 region_pos = block_pos;
stxxl::int64 region_size = block_size;
if (!free_space.empty())
{
sortseq::iterator succ = free_space.upper_bound(region_pos);
sortseq::iterator pred = succ;
if (pred != free_space.begin())
pred--;
if (pred != free_space.end())
{
if (pred->first <= region_pos && pred->first + pred->second > region_pos)
{
STXXL_THROW2(bad_ext_alloc, "disk_allocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " in empty space [" << pred->first << " + " << pred->second << "]");
}
}
if (succ != free_space.end())
{
if (region_pos <= succ->first && region_pos + region_size > succ->first)
{
STXXL_THROW2(bad_ext_alloc, "disk_allocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " which overlaps empty space [" << succ->first << " + " << succ->second << "]");
}
}
if (succ == free_space.end())
{
if (pred == free_space.end())
{
deallocation_error(block_pos, block_size, pred, succ);
assert(pred != free_space.end());
}
if ((*pred).first + (*pred).second == region_pos)
{
// coalesce with predecessor
region_size += (*pred).second;
region_pos = (*pred).first;
free_space.erase(pred);
}
}
else
{
if (free_space.size() > 1)
{
#if 0
if (pred == succ)
{
deallocation_error(block_pos, block_size, pred, succ);
assert(pred != succ);
}
#endif
bool succ_is_not_the_first = (succ != free_space.begin());
if ((*succ).first == region_pos + region_size)
{
// coalesce with successor
region_size += (*succ).second;
free_space.erase(succ);
//-tb: set succ to pred afterwards due to iterator invalidation
succ = pred;
}
if (succ_is_not_the_first)
{
if (pred == free_space.end())
{
deallocation_error(block_pos, block_size, pred, succ);
assert(pred != free_space.end());
}
if ((*pred).first + (*pred).second == region_pos)
{
// coalesce with predecessor
region_size += (*pred).second;
region_pos = (*pred).first;
free_space.erase(pred);
}
}
}
else
{
if ((*succ).first == region_pos + region_size)
{
// coalesce with successor
region_size += (*succ).second;
free_space.erase(succ);
}
}
}
}
free_space[region_pos] = region_size;
free_bytes += block_size;
//dump();
}
STXXL_END_NAMESPACE
// vim: et:ts=4:sw=4
|