scheduler cleanup

This commit is contained in:
nakst 2021-11-07 21:43:48 +00:00
parent c173fa1fd8
commit 095ff182a2
3 changed files with 48 additions and 53 deletions

View File

@ -1688,7 +1688,7 @@ void MMBalanceThread() {
// For every memory region... // For every memory region...
MMSpace *space = process->vmm; MMSpace *space = process->vmm;
GetCurrentThread()->SetAddressSpace(space); scheduler.SetTemporaryAddressSpace(space);
KMutexAcquire(&space->reserveMutex); KMutexAcquire(&space->reserveMutex);
LinkedItem<MMRegion> *item = pmm.nextRegionToBalance ? &pmm.nextRegionToBalance->itemNonGuard : space->usedRegionsNonGuard.firstItem; LinkedItem<MMRegion> *item = pmm.nextRegionToBalance ? &pmm.nextRegionToBalance->itemNonGuard : space->usedRegionsNonGuard.firstItem;
@ -1746,7 +1746,7 @@ void MMBalanceThread() {
} }
KMutexRelease(&space->reserveMutex); KMutexRelease(&space->reserveMutex);
GetCurrentThread()->SetAddressSpace(nullptr); scheduler.SetTemporaryAddressSpace(nullptr);
CloseHandleToObject(process, KERNEL_OBJECT_PROCESS); CloseHandleToObject(process, KERNEL_OBJECT_PROCESS);
} }
} }

View File

@ -30,24 +30,19 @@ enum ThreadTerminatableState : int8_t {
}; };
struct Thread { struct Thread {
void SetAddressSpace(MMSpace *space); // Set a temporary address space for the thread.
// Used by the asynchronous task threads,
// and the memory manager's balancer.
// ** Must be the first item in the structure; see MMArchSafeCopy. ** // ** Must be the first item in the structure; see MMArchSafeCopy. **
bool inSafeCopy; bool inSafeCopy;
LinkedItem<Thread> item; // Entry in relevent thread queue or blockedThreads list for mutexes/writer locks. LinkedItem<Thread> item; // Entry in relevent thread queue or blockedThreads list for mutexes/writer locks.
LinkedItem<Thread> allItem; // Entry in the allThreads list. LinkedItem<Thread> allItem; // Entry in the allThreads list.
LinkedItem<Thread> processItem; // Entry in the process's list of threads. LinkedItem<Thread> processItem; // Entry in the process's list of threads.
LinkedItem<Thread> *blockedItems; // Entries in the blockedThreads lists for events (not mutexes).
struct Process *process; struct Process *process;
EsObjectID id; EsObjectID id;
volatile uintptr_t cpuTimeSlices; volatile uintptr_t cpuTimeSlices;
volatile size_t handles; volatile size_t handles;
int executingProcessorID; uint32_t executingProcessorID;
uintptr_t userStackBase; uintptr_t userStackBase;
uintptr_t kernelStackBase; uintptr_t kernelStackBase;
@ -65,7 +60,7 @@ struct Thread {
volatile ThreadTerminatableState terminatableState; volatile ThreadTerminatableState terminatableState;
volatile bool executing; volatile bool executing;
volatile bool terminating; // Set when a request to terminate the thread has been registered. volatile bool terminating; // Set when a request to terminate the thread has been registered.
volatile bool paused; // Set to pause a thread, usually when it has crashed or being debugged. The scheduler will skip threads marked as paused when deciding what to run. volatile bool paused; // Set to pause a thread. Paused threads are not executed (unless the terminatableState prevents that).
volatile bool receivedYieldIPI; // Used to terminate a thread executing on a different processor. volatile bool receivedYieldIPI; // Used to terminate a thread executing on a different processor.
union { union {
@ -77,6 +72,7 @@ struct Thread {
}; };
struct { struct {
LinkedItem<Thread> *eventItems; // Entries in the blockedThreads lists (one per event).
KEvent *volatile events[ES_MAX_WAIT_COUNT]; KEvent *volatile events[ES_MAX_WAIT_COUNT];
volatile size_t eventCount; volatile size_t eventCount;
}; };
@ -214,6 +210,9 @@ struct Scheduler {
void WaitMutex(KMutex *mutex); void WaitMutex(KMutex *mutex);
uintptr_t WaitEvents(KEvent **events, size_t count); // Returns index of notified object. uintptr_t WaitEvents(KEvent **events, size_t count); // Returns index of notified object.
// Set a temporary address space for the current thread. Used by some asynchronous tasks, and the memory manager's balancer.
void SetTemporaryAddressSpace(MMSpace *space);
void Shutdown(); void Shutdown();
// Internal functions: // Internal functions:
@ -500,7 +499,7 @@ Thread *Scheduler::SpawnThread(const char *cName, uintptr_t startAddress, uintpt
void _RemoveProcess(KAsyncTask *task) { void _RemoveProcess(KAsyncTask *task) {
Process *process = EsContainerOf(Process, removeAsyncTask, task); Process *process = EsContainerOf(Process, removeAsyncTask, task);
GetCurrentThread()->SetAddressSpace(process->vmm); scheduler.SetTemporaryAddressSpace(process->vmm);
scheduler.RemoveProcess(process); scheduler.RemoveProcess(process);
} }
@ -578,7 +577,7 @@ void KillProcess(Process *process) {
void KillThread(KAsyncTask *task) { void KillThread(KAsyncTask *task) {
Thread *thread = EsContainerOf(Thread, killAsyncTask, task); Thread *thread = EsContainerOf(Thread, killAsyncTask, task);
GetCurrentThread()->SetAddressSpace(thread->process->vmm); scheduler.SetTemporaryAddressSpace(thread->process->vmm);
KMutexAcquire(&scheduler.allThreadsMutex); KMutexAcquire(&scheduler.allThreadsMutex);
scheduler.allThreads.Remove(&thread->allItem); scheduler.allThreads.Remove(&thread->allItem);
@ -923,18 +922,15 @@ Process *Scheduler::SpawnProcess(ProcessType processType) {
return process; return process;
} }
void Thread::SetAddressSpace(MMSpace *space) { void Scheduler::SetTemporaryAddressSpace(MMSpace *space) {
if (this != GetCurrentThread()) { KSpinlockAcquire(&lock);
KernelPanic("Thread::SetAddressSpace - Cannot change another thread's address space.\n"); Thread *thread = GetCurrentThread();
} MMSpace *oldSpace = thread->temporaryAddressSpace ?: kernelMMSpace;
thread->temporaryAddressSpace = space;
KSpinlockAcquire(&scheduler.lock);
MMSpace *oldSpace = temporaryAddressSpace ?: kernelMMSpace;
temporaryAddressSpace = space;
MMSpace *newSpace = space ?: kernelMMSpace; MMSpace *newSpace = space ?: kernelMMSpace;
MMSpaceOpenReference(newSpace); MMSpaceOpenReference(newSpace);
ProcessorSetAddressSpace(&newSpace->data); ProcessorSetAddressSpace(&newSpace->data);
KSpinlockRelease(&scheduler.lock); KSpinlockRelease(&lock);
MMSpaceCloseReference(oldSpace); MMSpaceCloseReference(oldSpace);
} }
@ -954,7 +950,7 @@ void AsyncTaskThread() {
item->Remove(); item->Remove();
KSpinlockRelease(&asyncTaskSpinlock); KSpinlockRelease(&asyncTaskSpinlock);
callback(task); // This may cause the task to be deallocated. callback(task); // This may cause the task to be deallocated.
local->currentThread->SetAddressSpace(nullptr); // The task may have modified the address space. scheduler.SetTemporaryAddressSpace(nullptr); // The task may have modified the address space.
local->inAsyncTask = false; local->inAsyncTask = false;
} }
} }
@ -1250,7 +1246,7 @@ void Scheduler::Yield(InterruptContext *context) {
if (!unblocked) { if (!unblocked) {
for (uintptr_t i = 0; i < local->currentThread->blocking.eventCount; i++) { for (uintptr_t i = 0; i < local->currentThread->blocking.eventCount; i++) {
local->currentThread->blocking.events[i]->blockedThreads.InsertEnd(&local->currentThread->blockedItems[i]); local->currentThread->blocking.events[i]->blockedThreads.InsertEnd(&local->currentThread->blocking.eventItems[i]);
} }
} }
} }
@ -1278,8 +1274,12 @@ void Scheduler::Yield(InterruptContext *context) {
} }
} }
// Notify any triggered timers. if (!local->processorID) {
// Update the scheduler's time.
timeMs = ArchGetTimeMs();
globalData->schedulerTimeMs = timeMs;
// Notify the necessary timers.
LinkedItem<KTimer> *_timer = activeTimers.firstItem; LinkedItem<KTimer> *_timer = activeTimers.firstItem;
while (_timer) { while (_timer) {
@ -1299,6 +1299,7 @@ void Scheduler::Yield(InterruptContext *context) {
_timer = next; _timer = next;
} }
}
// Get the next thread to execute. // Get the next thread to execute.
Thread *newThread = local->currentThread = PickThread(local); Thread *newThread = local->currentThread = PickThread(local);
@ -1322,12 +1323,6 @@ void Scheduler::Yield(InterruptContext *context) {
// Prepare the next timer interrupt. // Prepare the next timer interrupt.
ArchNextTimer(1 /* ms */); ArchNextTimer(1 /* ms */);
if (!local->processorID) {
// Update the scheduler's time.
timeMs = ArchGetTimeMs();
globalData->schedulerTimeMs = timeMs;
}
InterruptContext *newContext = newThread->interruptContext; InterruptContext *newContext = newThread->interruptContext;
MMSpace *addressSpace = newThread->temporaryAddressSpace ?: newThread->process->vmm; MMSpace *addressSpace = newThread->temporaryAddressSpace ?: newThread->process->vmm;
MMSpaceOpenReference(addressSpace); MMSpaceOpenReference(addressSpace);

View File

@ -666,13 +666,13 @@ uintptr_t Scheduler::WaitEvents(KEvent **events, size_t count) {
Thread *thread = GetCurrentThread(); Thread *thread = GetCurrentThread();
thread->blocking.eventCount = count; thread->blocking.eventCount = count;
LinkedItem<Thread> blockedItems[count]; // Max size 16 * 32 = 512. LinkedItem<Thread> eventItems[count]; // Max size 16 * 32 = 512.
EsMemoryZero(blockedItems, count * sizeof(LinkedItem<Thread>)); EsMemoryZero(eventItems, count * sizeof(LinkedItem<Thread>));
thread->blockedItems = blockedItems; thread->blocking.eventItems = eventItems;
EsDefer(thread->blockedItems = nullptr); EsDefer(thread->blocking.eventItems = nullptr);
for (uintptr_t i = 0; i < count; i++) { for (uintptr_t i = 0; i < count; i++) {
thread->blockedItems[i].thisItem = thread; eventItems[i].thisItem = thread;
thread->blocking.events[i] = events[i]; thread->blocking.events[i] = events[i];
} }
@ -741,8 +741,8 @@ void Scheduler::UnblockThread(Thread *unblockedThread, Thread *previousMutexOwne
} }
} else if (unblockedThread->state == THREAD_WAITING_EVENT) { } else if (unblockedThread->state == THREAD_WAITING_EVENT) {
for (uintptr_t i = 0; i < unblockedThread->blocking.eventCount; i++) { for (uintptr_t i = 0; i < unblockedThread->blocking.eventCount; i++) {
if (unblockedThread->blockedItems[i].list) { if (unblockedThread->blocking.eventItems[i].list) {
unblockedThread->blockedItems[i].RemoveFromList(); unblockedThread->blocking.eventItems[i].RemoveFromList();
} }
} }
} else if (unblockedThread->state == THREAD_WAITING_WRITER_LOCK) { } else if (unblockedThread->state == THREAD_WAITING_WRITER_LOCK) {