blob: b299efea263d9c0e9977b8e52d8a50b45bbe8c3e [file] [log] [blame]
/*
* Copyright (c) 2018-2019 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TestHarness.h"
#if TLC
#include "LargeSharingPoolDump.h"
#include "pas_epoch.h"
#include "pas_heap_lock.h"
#include "pas_large_sharing_pool.h"
#include "pas_page_malloc.h"
#include "pas_physical_memory_transaction.h"
#include "pas_scavenger.h"
#include <vector>
#define PG (pas_page_malloc_alignment())
#define END ((uintptr_t)1 << PAS_ADDRESS_BITS)
using namespace std;
namespace {
struct Range {
Range(uintptr_t begin,
uintptr_t end,
pas_commit_mode isCommitted,
size_t numLiveBytes,
uint64_t epoch)
: begin(begin)
, end(end)
, isCommitted(isCommitted)
, numLiveBytes(numLiveBytes)
, epoch(epoch)
{
}
uintptr_t begin;
uintptr_t end;
pas_commit_mode isCommitted;
size_t numLiveBytes;
uint64_t epoch;
};
void assertState(const vector<Range>& ranges)
{
size_t index = 0;
forEachLargeSharingPoolNode(
[&] (pas_large_sharing_node* node) -> bool {
CHECK_LESS(index, ranges.size());
Range expectedRange = ranges[index++];
CHECK_EQUAL(node->range.begin, expectedRange.begin);
CHECK_EQUAL(node->range.end, expectedRange.end);
CHECK_EQUAL(node->is_committed, expectedRange.isCommitted);
CHECK_EQUAL(node->num_live_bytes, expectedRange.numLiveBytes);
CHECK_EQUAL(node->use_epoch, expectedRange.epoch);
return true;
});
CHECK_EQUAL(index, ranges.size());
}
void testBadCoalesceEpochUpdate()
{
static constexpr bool verbose = false;
pas_physical_memory_transaction transaction;
pas_scavenger_suspend();
pas_physical_memory_transaction_construct(&transaction);
CHECK_EQUAL(pas_current_epoch, 0);
pas_heap_lock_lock();
pas_large_sharing_pool_boot_free(
pas_range_create(10 * PG, 20 * PG),
pas_physical_memory_is_locked_by_virtual_range_common_lock);
pas_heap_lock_unlock();
assertState({ Range(0, 10 * PG, pas_committed, 10 * PG, 0),
Range(10 * PG, 20 * PG, pas_committed, 0, 1),
Range(20 * PG, END, pas_committed, END - 20 * PG, 0) });
pas_heap_lock_lock();
pas_large_sharing_pool_boot_free(
pas_range_create(20 * PG, 30 * PG),
pas_physical_memory_is_locked_by_virtual_range_common_lock);
pas_heap_lock_unlock();
assertState({ Range(0, 10 * PG, pas_committed, 10 * PG, 0),
Range(10 * PG, 20 * PG, pas_committed, 0, 1),
Range(20 * PG, 30 * PG, pas_committed, 0, 2),
Range(30 * PG, END, pas_committed, END - 30 * PG, 0) });
pas_heap_lock_lock();
CHECK(pas_large_sharing_pool_allocate_and_commit(
pas_range_create(10 * PG, 30 * PG),
&transaction,
pas_physical_memory_is_locked_by_virtual_range_common_lock));
pas_heap_lock_unlock();
if (verbose)
dumpLargeSharingPool();
assertState({ Range(0, 10 * PG, pas_committed, 10 * PG, 0),
Range(10 * PG, 30 * PG, pas_committed, 20 * PG, 3),
Range(30 * PG, END, pas_committed, END - 30 * PG, 0) });
}
} // anonymous namespace
#endif // TLC
void addLargeSharingPoolTests()
{
#if TLC
EpochIsCounter epochIsCounter;
ADD_TEST(testBadCoalesceEpochUpdate());
#endif // TLC
}