lockless process count tracking

This commit is contained in:
nakst 2021-11-07 21:54:46 +00:00
parent cbedfce554
commit fb14dd87e0
1 changed files with 20 additions and 12 deletions

View File

@ -238,8 +238,8 @@ struct Scheduler {
KSpinlock activeTimersSpinlock; // For accessing the activeTimers lists. KSpinlock activeTimersSpinlock; // For accessing the activeTimers lists.
KEvent killedEvent; // Set during shutdown when all processes have been terminated. KEvent killedEvent; // Set during shutdown when all processes have been terminated.
uintptr_t blockShutdownProcessCount; volatile uintptr_t blockShutdownProcessCount;
size_t activeProcessCount; volatile size_t activeProcessCount;
Pool threadPool, processPool, mmSpacePool; Pool threadPool, processPool, mmSpacePool;
@ -532,10 +532,11 @@ void CloseHandleToProcess(void *_process) {
void KillProcess(Process *process) { void KillProcess(Process *process) {
KernelLog(LOG_INFO, "Scheduler", "killing process", "Killing process (%d) %x...\n", process->id, process); KernelLog(LOG_INFO, "Scheduler", "killing process", "Killing process (%d) %x...\n", process->id, process);
__sync_fetch_and_sub(&scheduler.activeProcessCount, 1);
KSpinlockAcquire(&scheduler.lock); KSpinlockAcquire(&scheduler.lock);
process->allThreadsTerminated = true; process->allThreadsTerminated = true;
scheduler.activeProcessCount--;
bool setProcessKilledEvent = true; bool setProcessKilledEvent = true;
@ -838,6 +839,8 @@ bool Process::Start(char *imagePath, size_t imagePathLength) {
} }
bool Process::StartWithNode(KNode *node) { bool Process::StartWithNode(KNode *node) {
// Make sure nobody has tried to start the process.
KSpinlockAcquire(&scheduler.lock); KSpinlockAcquire(&scheduler.lock);
if (executableStartRequest) { if (executableStartRequest) {
@ -849,6 +852,8 @@ bool Process::StartWithNode(KNode *node) {
KSpinlockRelease(&scheduler.lock); KSpinlockRelease(&scheduler.lock);
// Get the name of the process from the node.
KWriterLockTake(&node->writerLock, K_LOCK_SHARED); KWriterLockTake(&node->writerLock, K_LOCK_SHARED);
size_t byteCount = node->directoryEntry->item.key.longKeyBytes; size_t byteCount = node->directoryEntry->item.key.longKeyBytes;
if (byteCount > ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH) byteCount = ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH; if (byteCount > ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH) byteCount = ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH;
@ -856,6 +861,8 @@ bool Process::StartWithNode(KNode *node) {
cExecutableName[byteCount] = 0; cExecutableName[byteCount] = 0;
KWriterLockReturn(&node->writerLock, K_LOCK_SHARED); KWriterLockReturn(&node->writerLock, K_LOCK_SHARED);
// Initialise the memory space.
bool success = MMSpaceInitialise(vmm); bool success = MMSpaceInitialise(vmm);
if (!success) return false; if (!success) return false;
@ -866,13 +873,17 @@ bool Process::StartWithNode(KNode *node) {
} }
executableNode = node; executableNode = node;
__sync_fetch_and_add(&scheduler.activeProcessCount, 1);
__sync_fetch_and_add(&scheduler.blockShutdownProcessCount, 1);
// Add the process to the list of all processes.
KSpinlockAcquire(&scheduler.lock); KSpinlockAcquire(&scheduler.lock);
scheduler.allProcesses.InsertEnd(&allItem); scheduler.allProcesses.InsertEnd(&allItem);
scheduler.activeProcessCount++;
scheduler.blockShutdownProcessCount++;
KSpinlockRelease(&scheduler.lock); KSpinlockRelease(&scheduler.lock);
// Spawn the kernel thread to load the executable.
Thread *newProcessThread = scheduler.SpawnThread("NewProcess", (uintptr_t) NewProcess, 0, ES_FLAGS_DEFAULT, this); Thread *newProcessThread = scheduler.SpawnThread("NewProcess", (uintptr_t) NewProcess, 0, ES_FLAGS_DEFAULT, this);
if (!newProcessThread) { if (!newProcessThread) {
@ -880,6 +891,8 @@ bool Process::StartWithNode(KNode *node) {
return false; return false;
} }
// Wait for the executable to be loaded.
CloseHandleToObject(newProcessThread, KERNEL_OBJECT_THREAD); CloseHandleToObject(newProcessThread, KERNEL_OBJECT_THREAD);
KEventWait(&executableLoadAttemptComplete, ES_WAIT_NO_TIMEOUT); KEventWait(&executableLoadAttemptComplete, ES_WAIT_NO_TIMEOUT);
@ -1032,14 +1045,9 @@ void Scheduler::RemoveProcess(Process *process) {
if (started) { if (started) {
// If all processes (except the kernel process) have terminated, set the scheduler's killedEvent. // If all processes (except the kernel process) have terminated, set the scheduler's killedEvent.
KSpinlockAcquire(&scheduler.lock); if (1 == __sync_fetch_and_sub(&scheduler.blockShutdownProcessCount, 1)) {
scheduler.blockShutdownProcessCount--; KEventSet(&scheduler.killedEvent);
if (!scheduler.blockShutdownProcessCount) {
KEventSet(&scheduler.killedEvent, true, false);
} }
KSpinlockRelease(&scheduler.lock);
} }
} }