mirror of https://gitlab.com/nakst/essence
scheduler cleanup
This commit is contained in:
parent
c173fa1fd8
commit
095ff182a2
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,26 +1274,31 @@ void Scheduler::Yield(InterruptContext *context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify any triggered timers.
|
if (!local->processorID) {
|
||||||
|
// Update the scheduler's time.
|
||||||
|
timeMs = ArchGetTimeMs();
|
||||||
|
globalData->schedulerTimeMs = timeMs;
|
||||||
|
|
||||||
LinkedItem<KTimer> *_timer = activeTimers.firstItem;
|
// Notify the necessary timers.
|
||||||
|
LinkedItem<KTimer> *_timer = activeTimers.firstItem;
|
||||||
|
|
||||||
while (_timer) {
|
while (_timer) {
|
||||||
KTimer *timer = _timer->thisItem;
|
KTimer *timer = _timer->thisItem;
|
||||||
LinkedItem<KTimer> *next = _timer->nextItem;
|
LinkedItem<KTimer> *next = _timer->nextItem;
|
||||||
|
|
||||||
if (timer->triggerTimeMs <= timeMs) {
|
if (timer->triggerTimeMs <= timeMs) {
|
||||||
activeTimers.Remove(_timer);
|
activeTimers.Remove(_timer);
|
||||||
KEventSet(&timer->event, true /* scheduler already locked */);
|
KEventSet(&timer->event, true /* scheduler already locked */);
|
||||||
|
|
||||||
if (timer->callback) {
|
if (timer->callback) {
|
||||||
KRegisterAsyncTask(&timer->asyncTask, timer->callback);
|
KRegisterAsyncTask(&timer->asyncTask, timer->callback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break; // Timers are kept sorted, so there's no point continuing.
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
break; // Timers are kept sorted, so there's no point continuing.
|
|
||||||
}
|
|
||||||
|
|
||||||
_timer = next;
|
_timer = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next thread to execute.
|
// Get the next thread to execute.
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue