Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/ProcSim.Core/CPU.cs → src/ProcSim.Core/Cpu.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.Interruptions;
using ProcSim.Core.Interruptions;
using ProcSim.Core.Process;
using ProcSim.Core.Scheduler;
using ProcSim.Core.Syscall;
Expand All @@ -7,15 +7,15 @@

namespace ProcSim.Core;

public class CPU
public class Cpu
{
private readonly ConcurrentDictionary<PCB, List<Instruction>> _programs;
private readonly ConcurrentDictionary<Pcb, List<Instruction>> _programs;
private readonly InterruptController _interruptController;
private readonly InterruptService _isrv;
private List<Instruction> _instructions;
private ConcurrentQueue<MicroOp> _ops;

public CPU(uint id, InterruptController intc, InterruptService isrv, IScheduler sched, SystemCallDispatcher syscallDisp, ConcurrentDictionary<PCB, List<Instruction>> processPrograms, Action<Action> subscribeToTick)
public Cpu(uint id, InterruptController intc, InterruptService isrv, IScheduler sched, SystemCallDispatcher syscallDisp, ConcurrentDictionary<Pcb, List<Instruction>> processPrograms, Action<Action> subscribeToTick)
{
Comment thread
casuffitsharp marked this conversation as resolved.
Id = id;
_interruptController = intc;
Expand All @@ -34,7 +34,7 @@ public CPU(uint id, InterruptController intc, InterruptService isrv, IScheduler
}

public uint Id { get; }
public PCB CurrentPCB
public Pcb CurrentPCB
{
get;
set
Expand Down
10 changes: 5 additions & 5 deletions src/ProcSim.Core/Dispatcher.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using ProcSim.Core.Process;
using ProcSim.Core.Process;
using System.Diagnostics;
using System.Text.Json;

namespace ProcSim.Core;

public static class Dispatcher
{
public static void SwitchContext(CPU cpu, PCB next)
public static void SwitchContext(Cpu cpu, Pcb next)
{
PCB prev = cpu.CurrentPCB;
Pcb prev = cpu.CurrentPCB;
prev?.OnExitRunning(cpu.UserCycleCount, cpu.SyscallCycleCount);
if (prev == next)
{
Expand All @@ -29,7 +29,7 @@ public static void SwitchContext(CPU cpu, PCB next)
}
}

public static void SaveContext(CPU cpu, PCB pcb)
public static void SaveContext(Cpu cpu, Pcb pcb)
{
Debug.WriteLine($"Process {pcb.ProcessId} - Saving context (PC: {cpu.PC}, SP: {cpu.SP})");

Expand All @@ -42,7 +42,7 @@ public static void SaveContext(CPU cpu, PCB pcb)
Debug.WriteLine($"Process {pcb.ProcessId} - Saved PCB: {JsonSerializer.Serialize(pcb)}");
}

public static void LoadContext(CPU cpu, PCB pcb)
public static void LoadContext(Cpu cpu, Pcb pcb)
{
cpu.PC = pcb.ProgramCounter;
cpu.SP = pcb.StackPointer;
Expand Down
30 changes: 21 additions & 9 deletions src/ProcSim.Core/IO/IODevice.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.Interruptions;
using ProcSim.Core.Interruptions;
using ProcSim.Core.Monitoring.Models;
using ProcSim.Core.Process;
using System.Collections.Concurrent;
Expand All @@ -10,7 +10,7 @@ public class IODevice : IDisposable
{
private readonly BlockingCollection<IORequest> _queue = [];
private readonly InterruptController _interruptController;
private readonly ConcurrentQueue<PCB> _waiters = [];
private readonly ConcurrentQueue<Pcb> _waiters = [];
private readonly List<Task> _workers;
private bool _disposed;
private readonly CancellationTokenSource _cts;
Expand Down Expand Up @@ -44,31 +44,43 @@ public IODevice(uint deviceId, uint vector, uint baseLatency, InterruptControlle
public long TotalRequests => _totalRequests;
public long TotalProcessed => _totalProcessed;

public void Submit(PCB pcb, uint operationUnits)
public void Submit(Pcb pcb, uint operationUnits)
{
Debug.WriteLine($"IODevice {Id} - Received request from process {pcb.ProcessId} (Operation Units: {operationUnits})");
pcb.State = ProcessState.Waiting;
_queue.Add(new IORequest(pcb, operationUnits));
}

public IEnumerable<PCB> PopWaiters()
public IEnumerable<Pcb> PopWaiters()
{
if (!_waiters.TryDequeue(out PCB pcb))
if (!_waiters.TryDequeue(out Pcb pcb))
yield break;

yield return pcb;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;

_queue.CompleteAdding();
if (disposing)
{
// Dispose managed resources
_queue.CompleteAdding();
_cts.Cancel();
Task.WaitAll([.. _workers]);
_queue.Dispose();
_cts.Dispose();
}

_disposed = true;
_cts.Cancel();
Task.WaitAll([.. _workers]);
_queue.Dispose();
}

private async Task WorkerAsync(uint channelId, CancellationToken ct)
Expand Down
4 changes: 2 additions & 2 deletions src/ProcSim.Core/IO/IoRequest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using ProcSim.Core.Process;
using ProcSim.Core.Process;

namespace ProcSim.Core.IO;

public record IORequest(PCB Pcb, uint OperationUnits);
public record IORequest(Pcb Pcb, uint OperationUnits);
4 changes: 2 additions & 2 deletions src/ProcSim.Core/Interruptions/Handlers/IInterruptHandler.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using ProcSim.Core.Process;
using ProcSim.Core.Process;

namespace ProcSim.Core.Interruptions.Handlers;

public interface IInterruptHandler
{
bool CanHandle(uint vector);
Instruction BuildBody(uint vector, CPU cpu);
Instruction BuildBody(uint vector, Cpu cpu);
}
4 changes: 2 additions & 2 deletions src/ProcSim.Core/Interruptions/Handlers/IoInterruptHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.IO;
using ProcSim.Core.IO;
using ProcSim.Core.Process;
using ProcSim.Core.Process.Factories;

Expand All @@ -11,7 +11,7 @@ public bool CanHandle(uint vector)
return devices.ContainsKey(vector - 33);
}

public Instruction BuildBody(uint vector, CPU cpu)
public Instruction BuildBody(uint vector, Cpu cpu)
{
IODevice device = devices[vector - 33];
return InstructionFactory.HandleIo(device);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.Process;
using ProcSim.Core.Process;
using ProcSim.Core.Process.Factories;

namespace ProcSim.Core.Interruptions.Handlers;
Expand All @@ -12,7 +12,7 @@ public bool CanHandle(uint vector)
return vector == TimerVector;
}

public Instruction BuildBody(uint vector, CPU cpu)
public Instruction BuildBody(uint vector, Cpu cpu)
{
return InstructionFactory.ContextSwitch();
}
Expand Down
4 changes: 2 additions & 2 deletions src/ProcSim.Core/Interruptions/InterruptService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.Interruptions.Handlers;
using ProcSim.Core.Interruptions.Handlers;
using ProcSim.Core.Process;
using System.Diagnostics;

Expand All @@ -10,7 +10,7 @@ public class InterruptService(List<IInterruptHandler> handlers)

public long InterruptCount => _interruptCount;

public Instruction BuildISR(uint vector, CPU cpu)
public Instruction BuildISR(uint vector, Cpu cpu)
{
Interlocked.Increment(ref _interruptCount);
IInterruptHandler handler = handlers.First(h => h.CanHandle(vector));
Expand Down
38 changes: 26 additions & 12 deletions src/ProcSim.Core/Kernel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using ProcSim.Core.Interruptions;
using ProcSim.Core.Interruptions;
using ProcSim.Core.Interruptions.Handlers;
using ProcSim.Core.IO;
using ProcSim.Core.Monitoring;
using ProcSim.Core.Process;
using ProcSim.Core.Process.Factories;
using ProcSim.Core.Scheduler;
Expand All @@ -13,16 +12,17 @@ namespace ProcSim.Core;

public class Kernel : IDisposable
{
private readonly Dictionary<uint, PCB> _idlePcbs = [];
private readonly Dictionary<uint, Pcb> _idlePcbs = [];
private readonly InterruptController _interruptController = new();

private IScheduler _scheduler;
private bool _disposed;

public const uint KERNEL_TERMINATE_VECTOR = 31;

public Dictionary<uint, IODevice> Devices { get; } = [];
public Dictionary<uint, CPU> Cpus { get; } = [];
public ConcurrentDictionary<PCB, List<Instruction>> Programs { get; } = new();
public Dictionary<uint, Cpu> Cpus { get; } = [];
public ConcurrentDictionary<Pcb, List<Instruction>> Programs { get; } = new();
public ulong GlobalCycle { get; private set; }

public uint RegisterDevice(string name, uint baseLatency, uint channels)
Expand All @@ -48,11 +48,11 @@ public void Initialize(uint cores, uint quantum, SchedulerType schedulerType, Ac
for (uint coreId = 0; coreId < cores; coreId++)
{
List<Instruction> idleInstructions = [InstructionFactory.Idle()];
PCB idleProcess = new((int)coreId, $"Idle({coreId})", null, ProcessStaticPriority.Normal) { State = ProcessState.Ready };
Pcb idleProcess = new((int)coreId, $"Idle({coreId})", null, ProcessStaticPriority.Normal) { State = ProcessState.Ready };
_idlePcbs[coreId] = idleProcess;
Programs[idleProcess] = idleInstructions;

CPU cpu = new(coreId, _interruptController, interruptService, _scheduler, syscallDispatcher, Programs, subscribeToTick);
Cpu cpu = new(coreId, _interruptController, interruptService, _scheduler, syscallDispatcher, Programs, subscribeToTick);
Cpus.Add(coreId, cpu);

_interruptController.RegisterCore(coreId);
Expand All @@ -66,7 +66,7 @@ public void Initialize(uint cores, uint quantum, SchedulerType schedulerType, Ac
public int CreateProcess(ProcessDto program)
{
int id = Programs.Count;
PCB pcb = new(id, program.Name, program.Registers, program.Priority);
Pcb pcb = new(id, program.Name, program.Registers, program.Priority);
Programs[pcb] = [.. program.Instructions];
_scheduler.Admit(pcb);
return id;
Expand All @@ -80,7 +80,7 @@ public void TerminateProcess(int pid)
return;
}

PCB pcb = Programs.Keys.FirstOrDefault(p => p.ProcessId == pid);
Pcb pcb = Programs.Keys.FirstOrDefault(p => p.ProcessId == pid);
if (pcb?.State is null or ProcessState.Terminated)
return;

Expand All @@ -92,13 +92,27 @@ public void TerminateProcess(int pid)

public void SetProcessStaticPriority(int pid, ProcessStaticPriority newPriority)
{
PCB pcb = Programs.Keys.First(p => p.ProcessId == pid);
Pcb pcb = Programs.Keys.First(p => p.ProcessId == pid);
pcb.StaticPriority = newPriority;
}

public void Dispose()
{
foreach (IODevice device in Devices.Values)
device.Dispose();
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;

if (disposing)
{
foreach (IODevice device in Devices.Values)
device.Dispose();
}

_disposed = true;
}
}
38 changes: 25 additions & 13 deletions src/ProcSim.Core/Monitoring/MonitoringService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ProcSim.Core.IO;
using ProcSim.Core.IO;
using ProcSim.Core.Monitoring.Models;
using ProcSim.Core.Process;
using System.Collections.Concurrent;
Expand All @@ -15,7 +15,6 @@ public class MonitoringService : IDisposable
private readonly CancellationTokenSource _cts = new();

private readonly Dictionary<uint, CpuSnapshot> _prevCpu = [];
private ulong _prevGlobalCycle;
private readonly Dictionary<int, ulong> _prevProcCycles = [];
private readonly Dictionary<uint, Dictionary<uint, ChannelSnapshot>> _prevChan = [];
private readonly Dictionary<uint, ConcurrentDictionary<uint, bool>> _deviceChannelBusy = [];
Expand All @@ -24,6 +23,7 @@ public class MonitoringService : IDisposable
private readonly ConcurrentDictionary<IoRequestNotification, ulong> _ioStarts = [];

private Kernel _kernel;
private bool _disposed;

public MonitoringService()
{
Expand Down Expand Up @@ -73,12 +73,10 @@ public void SetKernel(Kernel kernel)
DeviceMetrics.Clear();

// inicializa snapshots de CPU e processos
foreach (CPU cpu in _kernel.Cpus.Values)
foreach (Cpu cpu in _kernel.Cpus.Values)
_prevCpu[cpu.Id] = new CpuSnapshot(cpu);

_prevGlobalCycle = kernel.GlobalCycle;

foreach (PCB pcb in kernel.Programs.Keys)
foreach (Pcb pcb in kernel.Programs.Keys)
_prevProcCycles[pcb.ProcessId] = 0;

foreach (IODevice device in kernel.Devices.Values)
Expand Down Expand Up @@ -114,7 +112,6 @@ private async Task CollectAsync(CancellationToken ct)

DateTime ts = DateTime.UtcNow;
ulong nowTick = _kernel.GlobalCycle;
_prevGlobalCycle = nowTick;

// 1) CPU por núcleo e agregados
ulong totalC = 0UL; // total de ticks em todas as CPUs
Expand All @@ -123,7 +120,7 @@ private async Task CollectAsync(CancellationToken ct)
ulong totalI = 0UL; // ticks de interrupção (sum of dI)
ulong totalIdle = 0UL; // ticks de idle (sum of dIdle)

foreach (CPU cpu in _kernel.Cpus.Values)
foreach (Cpu cpu in _kernel.Cpus.Values)
{
CpuSnapshot prev = _prevCpu[cpu.Id];

Expand Down Expand Up @@ -159,7 +156,7 @@ private async Task CollectAsync(CancellationToken ct)

processSnapshots.Add(new ProcessSnapshot(Pid: 0, Name: "Idle", State: idlePercent > 0 ? ProcessState.Running : ProcessState.Ready, CpuUsage: idlePercent, StaticPriority: ProcessStaticPriority.Normal, DynamicPriority: -1));

foreach (PCB pcb in _kernel.Programs.Keys)
foreach (Pcb pcb in _kernel.Programs.Keys)
{
if (pcb.ProcessId < _kernel.Cpus.Count)
continue;
Expand Down Expand Up @@ -270,14 +267,29 @@ private void OnIoRequestCompleted(IoRequestNotification req)

public void Dispose()
{
_cts.Cancel();
_timer.Dispose();
Debug.WriteLineIf(DebugEnabled, "[MonitoringService] Disposed");
Dispose(disposing: true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_cts.Cancel();
_cts.Dispose();
_timer.Dispose();
Debug.WriteLineIf(DebugEnabled, "[MonitoringService] Disposed");
}

_disposed = true;
}
}

private sealed record CpuSnapshot(ulong CycleCount, ulong UserCycleCount, ulong SyscallCycleCount, ulong InterruptCycleCount, ulong IdleCycleCount)
{
public CpuSnapshot(CPU cpu) : this(cpu.CycleCount, cpu.UserCycleCount, cpu.SyscallCycleCount, cpu.InterruptCycleCount, cpu.IdleCycleCount) { }
public CpuSnapshot(Cpu cpu) : this(cpu.CycleCount, cpu.UserCycleCount, cpu.SyscallCycleCount, cpu.InterruptCycleCount, cpu.IdleCycleCount) { }
}

private sealed record ChannelSnapshot
Expand Down
Loading
Loading