Kaydet (Commit) 271a663d authored tarafından Ashod Nakashian's avatar Ashod Nakashian Kaydeden (comit) Ashod Nakashian

rtl: support start/stop threads around pre-init

This is necessary to avoid having extra threads
while forking. After forking, the second stage
of pre-init is started and so we start the stopped
rtl threads.

The comment for rtl_alloc_preInit_phase_t has
more details.

Change-Id: I1a3f7be74d4b04d0b2fc4a72b02124c2faa3c047
Reviewed-on: https://gerrit.libreoffice.org/47060Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarAshod Nakashian <ashnakash@gmail.com>
üst 0217031a
......@@ -3552,7 +3552,9 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
return 1;
if (eStage == PRE_INIT)
rtl_alloc_preInit(true);
rtl_alloc_preInit(rtlAllocPreInitStart);
else if (eStage == SECOND_INIT)
rtl_alloc_preInit(rtlAllocPreInitEnd);
if (eStage != SECOND_INIT)
comphelper::LibreOfficeKit::setActive();
......@@ -3707,7 +3709,7 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
}
if (eStage == PRE_INIT)
rtl_alloc_preInit(false);
rtl_alloc_preInit(rtlAllocPostInit);
return bInitialized;
}
......
......@@ -288,6 +288,40 @@ SAL_DLLPUBLIC void SAL_CALL rtl_cache_free (
#ifdef LIBO_INTERNAL_ONLY
/** @cond INTERNAL */
/** rtl_alloc_preInit_phase_t
*
* This is used to control the pre-init logic
* in rtl_alloc_preInit. The reason for this is
* to first initialize all caching and other memory
* logic from WSD (the Online demaon) at startup.
* All these pages will then be forked over when
* spawning per-document instances. This is done
* by calling rtl_alloc_preInit with rtlAllocPreInitStart.
*
* However before forking we need to wind down
* all threads, which is required by design.
* This is done by calling rtl_alloc_preInit
* with rtlAllocPreInitEnd.
*
* And of course the stopped threads need restarting
* after forking to ensure correct cleanup of the
* caches and other memory allocations. This is done
* by calling rtl_alloc_preInit with rtlAllocPostInit.
*
* @since LibreOffice 6.1
*/
typedef enum
{
// Start phase I of pre-init.
rtlAllocPreInitStart,
// Finish phase I of pre-init (before forking).
rtlAllocPreInitEnd,
// Post pre-init and after forking.
rtlAllocPostInit
} rtl_alloc_preInit_phase_t;
/** @cond INTERNAL */
/** rtl_alloc_preInit
*
......@@ -295,9 +329,9 @@ SAL_DLLPUBLIC void SAL_CALL rtl_cache_free (
* at the end of LibreOfficeKit pre-initialization to enable
* various optimizations.
*
* Its function is to annotate a section @start = true to
* end (@start = false) via. two calls. Inside this section
* string allocators are replaced with ones which cause the
* Its function is to annotate a section @phase = rtlAllocPreInitStart
* to end (@phase = rtlAllocPreInitEnd) via. two calls. Inside this
* section string allocators are replaced with ones which cause the
* strings to be staticized at the end of the section.
*
* This brings a number of constraints - in particular no
......@@ -317,7 +351,7 @@ SAL_DLLPUBLIC void SAL_CALL rtl_cache_free (
* @since LibreOffice 6.1
*/
SAL_DLLPUBLIC void SAL_CALL rtl_alloc_preInit (
sal_Bool start
rtl_alloc_preInit_phase_t phase
) SAL_THROW_EXTERN_C();
/** @endcond */
......
......@@ -26,6 +26,10 @@ void rtl_cache_fini(void);
void ensureCacheSingleton(void);
void rtl_cache_stop_threads(void);
void rtl_cache_start_threads(void);
void rtl_memory_init(void);
void rtl_memory_fini(void);
......
......@@ -158,7 +158,7 @@ public:
const char *sample = "Hello World";
std::vector<OUString> aStrings;
rtl_alloc_preInit(true);
rtl_alloc_preInit(rtlAllocPreInitStart);
OUString aFoo("foo");
......@@ -183,7 +183,7 @@ public:
}
// should static-ize all the strings.
rtl_alloc_preInit(false);
rtl_alloc_preInit(rtlAllocPreInitEnd);
for (size_t i = 0; i < aStrings.size(); ++i)
CPPUNIT_ASSERT_MESSAGE( "static after.", (aStrings[i].pData->refCount & SAL_STRING_STATIC_FLAG) );
......
......@@ -1353,6 +1353,16 @@ rtl_cache_wsupdate_all(void * arg)
#endif
}
void rtl_cache_stop_threads(void)
{
rtl_cache_wsupdate_fini();
}
void rtl_cache_start_threads(void)
{
rtl_cache_wsupdate_init();
}
void rtl_cache_init()
{
{
......
......@@ -21,6 +21,7 @@
#include <assert.h>
#include <rtl/alloc.h>
#include <rtl/ustring.h>
#include <rtllifecycle.h>
#include "strimp.hxx"
#include "alloc_impl.hxx"
......@@ -93,25 +94,45 @@ static void mark_static(void *addr, sal_Size /* size */, void *)
str->refCount |= SAL_STRING_STATIC_FLAG;
}
void SAL_CALL rtl_alloc_preInit (sal_Bool start) SAL_THROW_EXTERN_C()
void SAL_CALL rtl_alloc_preInit (rtl_alloc_preInit_phase_t phase) SAL_THROW_EXTERN_C()
{
if (start)
switch (phase)
{
rtl_allocateString = pre_allocateStringFn;
rtl_freeString = pre_freeStringFn;
pre_arena = rtl_arena_create("pre-init strings", 4, 0,
nullptr, rtl_arena_alloc,
rtl_arena_free, 0);
}
else // back to normal
{
rtl_arena_foreach(pre_arena, mark_static, nullptr);
rtl_allocateString = rtl_allocateMemory;
rtl_freeString = rtl_freeMemory;
// TODO: also re-initialize main allocator as well.
case rtlAllocPreInitStart:
{
rtl_allocateString = pre_allocateStringFn;
rtl_freeString = pre_freeStringFn;
pre_arena = rtl_arena_create("pre-init strings", 4, 0,
nullptr, rtl_arena_alloc,
rtl_arena_free, 0);
// To be consistent (and to ensure the rtl_cache threads are started).
ensureCacheSingleton();
}
break;
case rtlAllocPreInitEnd:
// back to normal
{
rtl_arena_foreach(pre_arena, mark_static, nullptr);
rtl_allocateString = rtl_allocateMemory;
rtl_freeString = rtl_freeMemory;
// Stop the rtl cache thread to have no extra threads while forking.
rtl_cache_stop_threads();
// TODO: also re-initialize main allocator as well.
}
break;
case rtlAllocPostInit:
{
// We have forked and need to restart threads and anything
// that must start after forking.
rtl_cache_start_threads();
}
break;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment