blob: ef67518a799c7b7f062edda3c90936084b533ceb [file] [log] [blame]
/*
* Copyright (c) 2020-2021 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 "pas_config.h"
#if LIBPAS_ENABLED
#include "pas_thread_local_cache_layout_node.h"
#include "pas_local_view_cache.h"
#include "pas_local_view_cache_node.h"
#include "pas_redundant_local_allocator_node.h"
#include "pas_segregated_size_directory_inlines.h"
pas_segregated_size_directory*
pas_thread_local_cache_layout_node_get_directory(pas_thread_local_cache_layout_node node)
{
if (pas_is_wrapped_segregated_size_directory(node))
return pas_unwrap_segregated_size_directory(node);
if (pas_is_wrapped_redundant_local_allocator_node(node)){
return pas_compact_segregated_size_directory_ptr_load_non_null(
&pas_unwrap_redundant_local_allocator_node(node)->directory);
}
return pas_compact_segregated_size_directory_ptr_load_non_null(
&pas_unwrap_local_view_cache_node(node)->directory);
}
pas_allocator_index
pas_thread_local_cache_layout_num_allocator_indices(pas_thread_local_cache_layout_node node)
{
pas_segregated_size_directory* directory;
directory = pas_thread_local_cache_layout_node_get_directory(node);
if (pas_thread_local_cache_layout_node_represents_allocator(node))
return pas_segregated_size_directory_num_allocator_indices(directory);
return pas_segregated_size_directory_num_allocator_indices_for_allocator_size(
PAS_LOCAL_VIEW_CACHE_SIZE(pas_segregated_size_directory_view_cache_capacity(directory)));
}
static pas_allocator_index*
allocator_index_ptr(pas_thread_local_cache_layout_node node)
{
if (pas_is_wrapped_segregated_size_directory(node)) {
return &pas_segregated_size_directory_data_ptr_load(
&pas_unwrap_segregated_size_directory(node)->data)->allocator_index;
}
if (pas_is_wrapped_redundant_local_allocator_node(node))
return &pas_unwrap_redundant_local_allocator_node(node)->allocator_index;
return &pas_compact_segregated_size_directory_ptr_load_non_null(
&pas_unwrap_local_view_cache_node(node)->directory)->view_cache_index;
}
pas_allocator_index
pas_thread_local_cache_layout_node_get_allocator_index_generic(pas_thread_local_cache_layout_node node)
{
return *allocator_index_ptr(node);
}
pas_allocator_index
pas_thread_local_cache_layout_node_get_allocator_index_for_allocator(pas_thread_local_cache_layout_node node)
{
PAS_ASSERT(pas_thread_local_cache_layout_node_represents_allocator(node));
return pas_thread_local_cache_layout_node_get_allocator_index_generic(node);
}
pas_allocator_index
pas_thread_local_cache_layout_node_get_allocator_index_for_view_cache(pas_thread_local_cache_layout_node node)
{
PAS_ASSERT(pas_thread_local_cache_layout_node_represents_view_cache(node));
return pas_thread_local_cache_layout_node_get_allocator_index_generic(node);
}
void
pas_thread_local_cache_layout_node_set_allocator_index(pas_thread_local_cache_layout_node node,
pas_allocator_index index)
{
*allocator_index_ptr(node) = index;
}
static pas_compact_atomic_thread_local_cache_layout_node*
next_ptr(pas_thread_local_cache_layout_node node)
{
if (pas_is_wrapped_segregated_size_directory(node)) {
return &pas_segregated_size_directory_data_ptr_load(
&pas_unwrap_segregated_size_directory(node)->data)->next_for_layout;
}
if (pas_is_wrapped_redundant_local_allocator_node(node))
return &pas_unwrap_redundant_local_allocator_node(node)->next;
return &pas_unwrap_local_view_cache_node(node)->next;
}
pas_thread_local_cache_layout_node
pas_thread_local_cache_layout_node_get_next(pas_thread_local_cache_layout_node node)
{
return pas_compact_atomic_thread_local_cache_layout_node_load(next_ptr(node));
}
void pas_thread_local_cache_layout_node_set_next(pas_thread_local_cache_layout_node node,
pas_thread_local_cache_layout_node next_node)
{
pas_compact_atomic_thread_local_cache_layout_node_store(next_ptr(node), next_node);
}
void pas_thread_local_cache_layout_node_construct(pas_thread_local_cache_layout_node node,
pas_thread_local_cache* cache)
{
if (pas_thread_local_cache_layout_node_represents_allocator(node)) {
pas_local_allocator_construct(
pas_thread_local_cache_get_local_allocator_impl(
cache, pas_thread_local_cache_layout_node_get_allocator_index_for_allocator(node)),
pas_thread_local_cache_layout_node_get_directory(node));
return;
}
pas_local_view_cache_construct(
pas_thread_local_cache_get_local_allocator_impl(
cache, pas_thread_local_cache_layout_node_get_allocator_index_for_view_cache(node)),
pas_segregated_size_directory_view_cache_capacity(
pas_thread_local_cache_layout_node_get_directory(node)));
}
void pas_thread_local_cache_layout_node_move(pas_thread_local_cache_layout_node node,
pas_thread_local_cache* to_cache,
pas_thread_local_cache* from_cache)
{
pas_allocator_index allocator_index;
allocator_index = pas_thread_local_cache_layout_node_get_allocator_index_generic(node);
if (pas_thread_local_cache_layout_node_represents_allocator(node)) {
pas_local_allocator_move(
pas_thread_local_cache_get_local_allocator_impl(to_cache, allocator_index),
pas_thread_local_cache_get_local_allocator_impl(from_cache, allocator_index));
return;
}
pas_local_view_cache_move(
pas_thread_local_cache_get_local_allocator_impl(to_cache, allocator_index),
pas_thread_local_cache_get_local_allocator_impl(from_cache, allocator_index));
}
void pas_thread_local_cache_layout_node_stop(pas_thread_local_cache_layout_node node,
pas_thread_local_cache* cache,
pas_lock_lock_mode page_lock_mode,
pas_lock_hold_mode heap_lock_hold_mode)
{
static const bool verbose = false;
pas_allocator_index allocator_index;
void* allocator;
allocator_index = pas_thread_local_cache_layout_node_get_allocator_index_generic(node);
allocator = pas_thread_local_cache_get_local_allocator_impl(cache, allocator_index);
if (verbose)
pas_log("Stopping allocator %p because pas_thread_local_cache_stop_local_allocators\n", allocator);
if (pas_thread_local_cache_layout_node_represents_allocator(node)) {
pas_local_allocator_stop(allocator, page_lock_mode, heap_lock_hold_mode);
return;
}
pas_local_view_cache_stop(allocator, page_lock_mode);
}
#endif /* LIBPAS_ENABLED */