Core: Fixed allocator issue on thread exit

git-svn-id: svn://ultimatepp.org/upp/trunk@13410 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2019-06-17 21:28:11 +00:00
parent 6551749499
commit 4cce8cb98b
5 changed files with 40 additions and 29 deletions

View file

@ -449,6 +449,7 @@ struct Heap : BlkHeap<HugeHeapDetail, 4096> {
void LargeFreeRemoteRaw() { LargeFreeRemoteRaw(large_remote_list); large_remote_list = NULL; }
void LargeFreeRemote();
void FreeRemoteRaw();
void MoveLargeTo(Heap *to_heap);
void Shutdown();
static void AuxFinalCheck();

View file

@ -6,7 +6,7 @@ namespace Upp {
#include "HeapImp.h"
#define LLOG(x) // LOG((void *)this << ' ' << x)
#define LLOG(x) // DLOG(x) // LOG((void *)this << ' ' << x)
const char *asString(int i)
{
@ -63,15 +63,37 @@ void Heap::FreeRemoteRaw()
LargeFreeRemoteRaw();
}
void Heap::MoveLargeTo(Heap *to_heap)
{
while(large != large->next) {
DLink *ml = large->next;
LLOG("Large page " << asString(ml));
ml->Unlink();
ml->Link(to_heap->large);
LBlkHeader *h = ml->GetFirst();
for(;;) {
LLOG("Large block " << asString(h) << " size " << AsString(h->GetSize() * 256) << (h->IsFree() ? " free" : ""));
h->heap = to_heap;
if(h->IsFree()) {
h->UnlinkFree(); // will link it when adopting
to_heap->lheap.LinkFree(h);
}
if(h->IsLast())
break;
h = h->GetNextHeader();
}
}
}
void Heap::Shutdown()
{ // Move all active blocks, "orphans", to global aux heap
LLOG("Shutdown");
LLOG("**** Shutdown heap " << asString(this));
Mutex::Lock __(mutex);
Init();
RemoteFlushRaw(); // Move remote blocks to originating heaps
FreeRemoteRaw(); // Free all remotely freed blocks
for(int i = 0; i < NKLASS; i++) {
LLOG("Free cache " << i);
for(int i = 0; i < NKLASS; i++) { // move all small pages to aux (some heap will pick them later)
LLOG("Free cache " << asString(i));
FreeLink *l = cache[i];
while(l) {
FreeLink *h = l;
@ -101,19 +123,9 @@ void Heap::Shutdown()
LLOG("Orphan empty " << (void *)empty[i]);
}
}
while(large != large->next) { // Move all large pages to aux (some heap will pick them later)
DLink *ml = large->next;
ml->Unlink();
ml->Link(aux.large);
LBlkHeader *h = ml->GetFirst();
for(;;) {
h->heap = &aux;
if(h->IsLast())
break;
h = h->GetNextHeader();
}
}
MoveLargeTo(&aux); // move all large pages to aux, some heap will pick them later
memset(this, 0, sizeof(Heap));
LLOG("++++ Done Shutdown heap " << asString(this));
}
void Heap::DblCheck(Page *p)

View file

@ -88,11 +88,7 @@ void *Heap::LAlloc(size_t& size)
Mutex::Lock __(mutex);
aux.LargeFreeRemoteRaw();
if(aux.large->next != aux.large) {
while(aux.large->next != aux.large) { // adopt all abandoned large blocks
DLink *ml = aux.large->next;
ml->Unlink();
ml->Link(large);
}
aux.MoveLargeTo(this); // adopt all abandoned large blocks
ptr = TryLAlloc(i0, wcount);
if(ptr)
return ptr;

View file

@ -127,6 +127,7 @@ void *Heap::Allok(int k)
force_inline
void *Heap::AllocSz(size_t& sz)
{
LLOG("Alloc " << asString(sz));
Stat(sz);
if(sz <= 384) {
if(sz == 0)
@ -307,16 +308,17 @@ force_inline
Heap *ThreadHeap()
{
#ifdef COMPILER_MINGW
thread_local byte sHeap[sizeof(Heap)];
static FastMingwTls<Heap *> heap_tls;
Heap *heap = heap_tls;
if(!heap)
heap_tls = heap = (Heap *)sHeap;
return heap;
#else
thread_local Heap heap[1];
return heap;
thread_local Heap *heap_tls;
#endif
Heap *heap = heap_tls;
if(!heap) { // we definitely need a lock here because some Shutdown can be in progress
Mutex::Lock __(Heap::mutex);
thread_local byte sHeap[sizeof(Heap)];
heap_tls = heap = (Heap *)sHeap;
}
return heap;
}
void MemoryFreek__(int klass, void *ptr)

View file

@ -876,7 +876,7 @@ void FileSel::LIThread()
Image result;
if(path.GetCount())
li(path, result);
if(!IsNull(result) && result.GetWidth() > DPI(16) || result.GetHeight() > DPI(16))
if(!IsNull(result) && max(result.GetWidth(), result.GetHeight()) > DPI(16))
result = Rescale(result, DPI(16), DPI(16));
{
Mutex::Lock __(li_mutex);