feat: add MLFQ scheduling algorithm and thread scheduler

- Implemented MLFQ (Multilevel Feedback Queue) algorithm with dynamic priority levels and quantum management.
- Created unit tests for MLFQ algorithm covering initialization, demotion, selection, priority boost, preemption, and quantum expiration.
- Developed a ThreadScheduler class supporting FCFS, RR, and PRIORITY scheduling policies for intra-process thread management.
- Added unit tests for ThreadScheduler to validate thread selection and quantum expiration logic.
This commit is contained in:
Lucas Guerra committed 2026-03-24 23:09:16 -03:00
1 parent 532c14e382
commit 5761dfe70a
34 files changed
+3789 -334

No files matched your search

+101 -1
View File
@@ -147,7 +147,7 @@ The process with the **highest ratio** is selected. This naturally increases the
## Multilevel Queue
**Type:** Preemptive
**Type:** Preemptive
**Parameters:** number of queues, quantum per queue
### How it works
@@ -158,6 +158,106 @@ This allows different classes of processes to be treated distinctly: for example
---
## MLFQ (Multilevel Feedback Queue)
**Type:** Preemptive
**Parameters:** number of queues, quantum per queue (default: [2, 4, 8]), boost interval
### How it works
MLFQ is an extension of the Multilevel Queue that allows **processes to move between queues** based on their observed runtime behavior — eliminating the need to know burst durations in advance.
#### Movement rules
| Event | Action |
|-------|--------|
| Newly arrived process | Enters **queue 0** (highest priority) |
| Process exhausts the quantum of its current queue | **Demoted** to the next queue (lower priority) |
| Process returns from I/O | Stays in the **same queue** (cooperative behavior is rewarded) |
| Boost tick (configurable interval) | **All** processes are moved to queue 0 |
#### Why is MLFQ efficient?
- Interactive processes (I/O Bound) naturally stay in high-priority queues because they leave the CPU before exhausting the quantum.
- Batch processes (CPU Bound) progressively migrate to lower-priority queues where they receive larger quantums.
- The periodic boost prevents starvation: even processes that fell to lower queues eventually return to the top.
#### Example with 3 queues (quantums: 2, 4, 8)
```
Process A (CPU Bound, burst=12):
Queue 0 → uses 2 ticks, demoted → Queue 1
Queue 1 → uses 4 ticks, demoted → Queue 2
Queue 2 → uses remaining 6 ticks (quantum=8, not exhausted)
Process B (I/O Bound, burst=1 CPU + I/O + burst=1 CPU):
Queue 0 → uses 1 tick → goes to I/O → returns to Queue 0
→ always stays in the highest-priority queue
```
### Parameters
| Parameter | Default | Description |
|-----------|---------|-------------|
| Number of queues | 3 | Number of priority queues |
| Quantum per queue | [2, 4, 8] | Time slice for each queue |
| Boost interval | 20 ticks | Every N ticks, all processes move up to queue 0 |
---
## Thread Models
PSS supports **thread** simulation within processes, implementing the three classical models described in Operating Systems textbooks.
### General Concepts
- A process can have **N user threads**, each with its own burst sequence (CPU and I/O).
- The scheduling policy among threads within the same process is configurable: **FCFS**, **Round Robin**, or **Priority**.
- The thread model determines how user threads map to kernel threads.
### MANY_TO_ONE (N:1)
**N user threads → 1 kernel thread**
- Only one thread can use the CPU at a time within the process.
- If any thread initiates I/O, **the entire process blocks** (the kernel thread is stuck).
- No real parallelism; very simple to implement.
- Simulated by the `many_to_one` presets.
### ONE_TO_ONE (1:1)
**Each user thread → 1 dedicated kernel thread**
- Threads block **independently**: if Thread A does I/O, Threads B and C remain in the Ready queue.
- The process only terminates when **all** threads have terminated.
- The process blocks only when all threads are simultaneously in I/O.
- Simulated by the `one_to_one` presets.
### MANY_TO_MANY (N:M)
**N user threads → M kernel threads (M ≤ N)**
- The number of kernel threads (`kernelThreadCount`) is configurable.
- If all M kernel slots are occupied, additional user threads wait in the **kernel wait queue** (`KernelWait`).
- Combines flexibility with resource control: more active threads than N:1 but less overhead than 1:1.
- Simulated by the `many_to_many` presets.
### Intra-Process Policy
Defines how the scheduler selects the next thread when multiple threads are Ready within the same process:
| Policy | Behavior |
|--------|----------|
| **FCFS** | The oldest thread in the Ready queue is selected |
| **Round Robin (RR)** | Each thread receives `threadQuantum` ticks; when exhausted, it goes to the end of the queue |
| **Priority** | The highest-priority thread is selected; immediate preemption if a higher-priority thread becomes ready |
### Gantt Chart with Threads
When a process has threads, the Gantt chart displays **sub-rows** below the process row, one per thread, with colors derived from the process color (40° hue shift per thread). The state of each thread (New, Ready, Running, Waiting, Terminated) is colored using the same CSS variables as process states.
---
## References
- Silberschatz, A., Galvin, P. B., & Gagne, G., *Operating System Concepts*, 10th edition.