drain work queue before exit

This commit is contained in:
nakst 2021-09-17 20:29:15 +01:00
parent 069eb7754f
commit a60f0cea09
5 changed files with 40 additions and 17 deletions

View File

@ -548,7 +548,7 @@ void ThumbnailResize(uint32_t *bits, uint32_t originalWidth, uint32_t originalHe
void ThumbnailGenerateTask(Instance *, Task *task) { void ThumbnailGenerateTask(Instance *, Task *task) {
EsMessageMutexAcquire(); EsMessageMutexAcquire();
Thumbnail *thumbnail = thumbnailCache.Get(&task->id); Thumbnail *thumbnail = thumbnailCache.Get(&task->id);
bool cancelTask = !thumbnail || thumbnail->referenceCount == 0; bool cancelTask = !thumbnail || thumbnail->referenceCount == 0 || EsWorkIsExiting();
EsMessageMutexRelease(); EsMessageMutexRelease();
if (cancelTask) { if (cancelTask) {
@ -593,13 +593,6 @@ void ThumbnailGenerateTask(Instance *, Task *task) {
if (targetWidth == originalWidth && targetHeight == originalHeight) { if (targetWidth == originalWidth && targetHeight == originalHeight) {
targetBits = originalBits; targetBits = originalBits;
} else { } else {
targetBits = (uint32_t *) EsHeapAllocate(targetWidth * targetHeight * 4, false);
if (!targetBits) {
EsHeapFree(originalBits);
return; // Allocation failure; could not resize the image.
}
ThumbnailResize(originalBits, originalWidth, originalHeight, targetWidth, targetHeight); ThumbnailResize(originalBits, originalWidth, originalHeight, targetWidth, targetHeight);
targetBits = (uint32_t *) EsHeapReallocate(originalBits, targetWidth * targetHeight * 4, false); targetBits = (uint32_t *) EsHeapReallocate(originalBits, targetWidth * targetHeight * 4, false);
} }

View File

@ -145,6 +145,8 @@ struct {
EsHandle workAvailable; EsHandle workAvailable;
EsMutex workMutex; EsMutex workMutex;
Array<Work> workQueue; Array<Work> workQueue;
Array<EsHandle> workThreads;
volatile bool workFinish;
} api; } api;
ptrdiff_t tlsStorageOffset; ptrdiff_t tlsStorageOffset;
@ -862,7 +864,17 @@ EsMessage *EsMessageReceive() {
// Desktop tracks the number of instances it owns, so it needs to know when it exits. // Desktop tracks the number of instances it owns, so it needs to know when it exits.
ApplicationProcessTerminated(EsProcessGetID(ES_CURRENT_PROCESS)); ApplicationProcessTerminated(EsProcessGetID(ES_CURRENT_PROCESS));
} else { } else {
api.workFinish = true;
if (api.workAvailable) EsEventSet(api.workAvailable);
EsMessageMutexRelease();
for (uintptr_t i = 0; i < api.workThreads.Length(); i++) {
EsWaitSingle(api.workThreads[i]);
EsHandleClose(api.workThreads[i]);
}
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
EsMessageMutexAcquire();
FontDatabaseFree(); FontDatabaseFree();
FreeUnusedStyles(true /* include permanent styles */); FreeUnusedStyles(true /* include permanent styles */);
theming.loadedStyles.Free(); theming.loadedStyles.Free();
@ -875,8 +887,9 @@ EsMessage *EsMessageReceive() {
gui.allWindows.Free(); gui.allWindows.Free();
calculator.Free(); calculator.Free();
HashTableFree(&gui.keyboardShortcutNames, false); HashTableFree(&gui.keyboardShortcutNames, false);
EsHandleClose(api.workAvailable); // TODO Waiting for all work to finish. if (api.workAvailable) EsHandleClose(api.workAvailable);
EsAssert(!api.workQueue.Length()); EsAssert(!api.workQueue.Length());
api.workThreads.Free();
api.workQueue.Free(); api.workQueue.Free();
MemoryLeakDetectorCheckpoint(&heap); MemoryLeakDetectorCheckpoint(&heap);
EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d (%d from malloc).\n", heap.allocationsCount, mallocCount); EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d (%d from malloc).\n", heap.allocationsCount, mallocCount);
@ -1893,6 +1906,10 @@ void EsTimerCancel(EsTimer id) {
EsMutexRelease(&api.timersMutex); EsMutexRelease(&api.timersMutex);
} }
bool EsWorkIsExiting() {
return api.workFinish;
}
void WorkThread(EsGeneric) { void WorkThread(EsGeneric) {
while (true) { while (true) {
EsWait(&api.workAvailable, 1, ES_WAIT_NO_TIMEOUT); EsWait(&api.workAvailable, 1, ES_WAIT_NO_TIMEOUT);
@ -1907,28 +1924,38 @@ void WorkThread(EsGeneric) {
work.callback(work.context); work.callback(work.context);
} else { } else {
EsMutexRelease(&api.workMutex); EsMutexRelease(&api.workMutex);
if (api.workFinish) {
EsEventSet(api.workAvailable); // Wake up another thread.
return;
} else {
break;
}
} }
} }
} }
} }
void EsWorkQueue(EsWorkCallback callback, EsGeneric context) { EsError EsWorkQueue(EsWorkCallback callback, EsGeneric context) {
EsMutexAcquire(&api.workMutex); EsMutexAcquire(&api.workMutex);
if (!api.workAvailable) { if (!api.workAvailable) {
api.workAvailable = EsEventCreate(true /* autoReset */); api.workAvailable = EsEventCreate(true /* autoReset */);
EsThreadInformation thread = {}; }
for (uintptr_t i = 0; i < EsSystemGetOptimalWorkQueueThreadCount(); i++) { EsThreadInformation thread = {};
EsThreadCreate(WorkThread, &thread, nullptr);
EsHandleClose(thread.handle); while (api.workThreads.Length() < EsSystemGetOptimalWorkQueueThreadCount()) {
} EsError error = EsThreadCreate(WorkThread, &thread, nullptr);
if (error != ES_SUCCESS) return error;
api.workThreads.Add(thread.handle);
} }
Work work = { callback, context }; Work work = { callback, context };
api.workQueue.Add(work); bool success = api.workQueue.Add(work);
EsMutexRelease(&api.workMutex); EsMutexRelease(&api.workMutex);
EsEventSet(api.workAvailable); EsEventSet(api.workAvailable);
return success ? ES_SUCCESS : ES_ERROR_INSUFFICIENT_RESOURCES;
} }
#ifndef ENABLE_POSIX_SUBSYSTEM #ifndef ENABLE_POSIX_SUBSYSTEM

View File

@ -1997,7 +1997,8 @@ function EsError EsThreadCreate(EsThreadEntryCallback entryFunction, EsThreadInf
function EsObjectID EsThreadGetID(EsHandle thread); function EsObjectID EsThreadGetID(EsHandle thread);
function void EsThreadTerminate(EsHandle thread); function void EsThreadTerminate(EsHandle thread);
function void EsWorkQueue(EsWorkCallback callback, EsGeneric context); function EsError EsWorkQueue(EsWorkCallback callback, EsGeneric context);
function bool EsWorkIsExiting();
// Memory. // Memory.

View File

@ -996,6 +996,7 @@ extern "C" void InterruptHandler(InterruptContext *context) {
while (rbp && traceDepth < 32) { while (rbp && traceDepth < 32) {
uint64_t value; uint64_t value;
if (!MMArchIsBufferInUserRange(rbp, 16)) break;
if (!MMArchSafeCopy((uintptr_t) &value, rbp + 8, sizeof(uint64_t))) break; if (!MMArchSafeCopy((uintptr_t) &value, rbp + 8, sizeof(uint64_t))) break;
EsPrint("\t%d: %x\n", ++traceDepth, value); EsPrint("\t%d: %x\n", ++traceDepth, value);
if (!value) break; if (!value) break;

View File

@ -454,3 +454,4 @@ EsFontDatabaseLookupByName=452
_EsWindowGetHandle=453 _EsWindowGetHandle=453
_EsUISetFont=454 _EsUISetFont=454
EsWorkQueue=455 EsWorkQueue=455
EsWorkIsExiting=456