1
0
Fork 0
libreoffice/sal/rtl/alloc_cache.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

225 lines
5.4 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "alloc_cache.hxx"
#include "alloc_impl.hxx"
#include "alloc_arena.hxx"
#include <rtllifecycle.h>
#include <cassert>
#include <cstdlib>
#include <string.h>
#include <stdio.h>
/**
provided for cache_type allocations, and hash_table resizing.
@internal
*/
static rtl_arena_type * gp_cache_arena = nullptr;
namespace
{
rtl_cache_type * rtl_cache_activate(
rtl_cache_type * cache,
const char * name,
size_t objsize,
size_t objalign,
int (SAL_CALL * constructor)(void * obj, void * userarg),
void (SAL_CALL * destructor) (void * obj, void * userarg),
void * userarg
)
{
assert(cache);
snprintf (cache->m_name, sizeof(cache->m_name), "%s", name);
if (objalign == 0)
{
/* determine default alignment */
if (objsize >= RTL_MEMORY_ALIGNMENT_8)
objalign = RTL_MEMORY_ALIGNMENT_8;
else
objalign = RTL_MEMORY_ALIGNMENT_4;
}
else
{
/* ensure minimum alignment */
if(objalign < RTL_MEMORY_ALIGNMENT_4)
{
objalign = RTL_MEMORY_ALIGNMENT_4;
}
}
assert(RTL_MEMORY_ISP2(objalign));
cache->m_type_size = RTL_MEMORY_P2ROUNDUP(objsize, objalign);
cache->m_constructor = constructor;
cache->m_destructor = destructor;
cache->m_userarg = userarg;
return cache;
}
} //namespace
rtl_cache_type * SAL_CALL rtl_cache_create(
const char * name,
sal_Size objsize,
sal_Size objalign,
int (SAL_CALL * constructor)(void * obj, void * userarg),
void (SAL_CALL * destructor) (void * obj, void * userarg),
void (SAL_CALL * /*reclaim*/) (void * userarg),
void * userarg,
rtl_arena_type *,
int
) noexcept
{
rtl_cache_type * result = nullptr;
sal_Size size = sizeof(rtl_cache_type);
try_alloc:
result = static_cast<rtl_cache_type*>(rtl_arena_alloc (gp_cache_arena, &size));
if (result)
{
rtl_cache_type * cache = result;
memset (cache, 0, sizeof(rtl_cache_type));
result = rtl_cache_activate (
cache,
name,
objsize,
objalign,
constructor,
destructor,
userarg
);
if (!result)
{
/* activation failed */
rtl_arena_free (gp_cache_arena, cache, size);
}
}
else if (!gp_cache_arena)
{
ensureCacheSingleton();
if (gp_cache_arena)
{
/* try again */
goto try_alloc;
}
}
return result;
}
void SAL_CALL rtl_cache_destroy(rtl_cache_type * cache) noexcept
{
if (cache)
{
rtl_arena_free (gp_cache_arena, cache, sizeof(rtl_cache_type));
}
}
void * SAL_CALL rtl_cache_alloc(rtl_cache_type * cache) noexcept
{
void * obj = nullptr;
if (!cache)
return nullptr;
obj = std::malloc(cache->m_type_size);
if (obj && cache->m_constructor)
{
if (!(cache->m_constructor)(obj, cache->m_userarg))
{
/* construction failure */
std::free(obj);
obj = nullptr;
}
}
return obj;
}
void SAL_CALL rtl_cache_free(
rtl_cache_type * cache,
void * obj
) noexcept
{
if (obj && cache)
{
if (cache->m_destructor)
{
/* destruct object */
(cache->m_destructor)(obj, cache->m_userarg);
}
std::free(obj);
}
}
#if defined(SAL_UNX)
void SAL_CALL rtl_secureZeroMemory(void *Ptr, sal_Size Bytes) noexcept
{
//currently glibc doesn't implement memset_s
volatile char *p = static_cast<volatile char*>(Ptr);
while (Bytes--)
*p++ = 0;
}
#elif defined(_WIN32)
void SAL_CALL rtl_secureZeroMemory(void *Ptr, sal_Size Bytes) noexcept
{
RtlSecureZeroMemory(Ptr, Bytes);
}
#endif /* SAL_UNX || _WIN32 */
void rtl_cache_init()
{
/* cache: internal arena */
assert(!gp_cache_arena);
gp_cache_arena = rtl_arena_create (
"rtl_cache_internal_arena",
64, /* quantum */
0, /* no quantum caching */
nullptr, /* default source */
rtl_arena_alloc,
rtl_arena_free,
0 /* flags */
);
assert(gp_cache_arena);
/* check 'gp_default_arena' initialization */
assert(gp_default_arena);
}
void rtl_cache_fini()
{
if (gp_cache_arena)
{
rtl_arena_destroy (gp_cache_arena);
gp_cache_arena = nullptr;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */