This repository has been archived by the owner on Aug 11, 2019. It is now read-only.
Resolve all known deadlock issues with PIT scheduling #6
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I've combined various fixes from robert-w-gries/rxinu#47, robert-w-gries/rxinu#49, and robert-w-gries/rxinu#52 to stabilize scheduling in
lambdaOS
.There was significant refactoring effort to ensure that all critical sections of the kernel is safely wrapped in
disable_interrupts_and_then()
. I've generally kept the naming conventions I used inrxinu
. If you have any preferences for naming or code organization, let me know.I can comfortably say that the scheduling code is stable now because
lambdaOS
is able to create and run1500
processes without deadlocking or running out of memory. Keyboard input still works while the null process is running and input also works after the final process is created and ran.Restoring interrupts instead of enabling all interrupts
Derived from robert-w-gries/rxinu#47
Previously, the
disable_interrupts_and_then()
function would globally disable interrupts, run some important kernel code, then it would globally enable interrupts.This procedure worked when the null process called
resched()
because we could ensure thatresched()
would only be called at one point in the kernel.After moving
resched()
to the timer handler, the kernel could now see aresched()
call at any time when interrupts are enabled. This led to various deadlock issues where interrupts would be called when we didn't expect it.My solution was to add many
disable_interrupts_and_then()
wrappers to any section of the kernel that held a lock (such as the Heap Allocator). This led to some nested calls todisable_interrupts_and_then()
. Since the wrapper globally enables interrupts after running code, interrupts were re-enabled inside of adisable_interrupts_and_then()
lower in the call stack. Thus, code that was expected to run interrupted was actually being interrupted.To solve this problem, I modified
disable_interrupts_and_then()
to save the interrupt masks of the Chained PICS. Now, we can nest calls todisable_interrupts_and_then()
as much as we want because the inner calls will see that the interrupt mask registers should be0xFF
.Refactoring the Heap Allocator
A consequence of using the PIT to schedule processes is that the Heap Allocator could be interrupted during allocation or de-allocation. Since our allocator is implemented with a
Mutex
wrapper, we need to ensure that allocation is not interrupted while the lock is held.Your previous organization of the global allocator did not allow me to wrap the
alloc
methods indisable_interrupts_and_then()
, so I needed to move the heap allocator code tosrc/memory/heap_allocator.rs
.Notes
PIT_TICKS
was not being reset, so I added that fix to this PR