[kernel] Schedule threads on other CPUs
Now that the other CPUs have been brought up, add support for scheduling tasks on them. The scheduler now maintains separate ready/blocked lists per CPU, and CPUs will attempt to balance load via periodic work stealing. Other changes as a result of this: - The device manager no longer creates a local APIC object, but instead just gathers relevant info from the APCI tables. Each CPU creates its own local APIC object. This also spurred the APIC timer calibration to become a static value, as all APICs are assumed to be symmetrical. - Fixed a bug where the scheduler was popping the current task off of its ready list, however the current task is never on the ready list (except the idle task was first set up as both current and ready). This was causing the lists to get into bad states. Now a task can only ever be current or in a ready or blocked list. - Got rid of the unused static process::s_processes list of all processes, instead of trying to synchronize it via locks. - Added spinlocks for synchronization to the scheduler and logger objects.
This commit is contained in:
@@ -24,10 +24,6 @@ public:
|
||||
/// \returns A reference to the system device manager
|
||||
static device_manager & get() { return s_instance; }
|
||||
|
||||
/// Get the LAPIC
|
||||
/// \returns An object representing the local APIC
|
||||
lapic & get_lapic() { return *m_lapic; }
|
||||
|
||||
/// Get an IOAPIC
|
||||
/// \arg i Index of the requested IOAPIC
|
||||
/// \returns An object representing the given IOAPIC if it exists,
|
||||
@@ -68,6 +64,39 @@ public:
|
||||
/// \returns True if the interrupt was handled
|
||||
bool dispatch_irq(unsigned irq);
|
||||
|
||||
struct apic_nmi
|
||||
{
|
||||
uint8_t cpu;
|
||||
uint8_t lint;
|
||||
uint16_t flags;
|
||||
};
|
||||
|
||||
struct irq_override
|
||||
{
|
||||
uint8_t source;
|
||||
uint16_t flags;
|
||||
uint32_t gsi;
|
||||
};
|
||||
|
||||
/// Get the list of APIC ids for other CPUs
|
||||
inline const kutil::vector<uint8_t> & get_apic_ids() const { return m_apic_ids; }
|
||||
|
||||
/// Get the LAPIC base address
|
||||
/// \returns The physical base address of the local apic registers
|
||||
uintptr_t get_lapic_base() const { return m_lapic_base; }
|
||||
|
||||
/// Get the NMI mapping for the given local APIC
|
||||
/// \arg id ID of the local APIC
|
||||
/// \returns apic_nmi structure describing the NMI configuration,
|
||||
/// or null if no configuration was provided
|
||||
const apic_nmi * get_lapic_nmi(uint8_t id) const;
|
||||
|
||||
/// Get the IRQ source override for the given IRQ
|
||||
/// \arg irq IRQ number (not isr vector)
|
||||
/// \returns irq_override structure describing that IRQ's
|
||||
/// configuration, or null if no configuration was provided
|
||||
const irq_override * get_irq_override(uint8_t irq) const;
|
||||
|
||||
/// Register the existance of a block device.
|
||||
/// \arg blockdev Pointer to the block device
|
||||
void register_block_device(block_device *blockdev);
|
||||
@@ -94,9 +123,6 @@ public:
|
||||
&m_hpets[i] : nullptr;
|
||||
}
|
||||
|
||||
/// Get the list of APIC ids for other CPUs
|
||||
inline const kutil::vector<uint8_t> & get_apic_ids() const { return m_apic_ids; }
|
||||
|
||||
private:
|
||||
/// Parse the ACPI XSDT and load relevant sub-tables.
|
||||
/// \arg xsdt Pointer to the XSDT from the firmware
|
||||
@@ -122,10 +148,13 @@ private:
|
||||
/// that has no callback.
|
||||
void bad_irq(uint8_t irq);
|
||||
|
||||
lapic *m_lapic;
|
||||
uintptr_t m_lapic_base;
|
||||
|
||||
kutil::vector<ioapic> m_ioapics;
|
||||
kutil::vector<hpet> m_hpets;
|
||||
kutil::vector<uint8_t> m_apic_ids;
|
||||
kutil::vector<apic_nmi> m_nmis;
|
||||
kutil::vector<irq_override> m_overrides;
|
||||
|
||||
kutil::vector<pci_group> m_pci;
|
||||
kutil::vector<pci_device> m_devices;
|
||||
|
||||
Reference in New Issue
Block a user