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
	
	 nakst
						nakst