StuBS
Guard Namespace Reference

Synchronizes the kernel with interrupts using the Prologue/Epilogue Model. More...

Functions

bool active ()
 Helper to check if we are currently in a guarded environment on this CPU core.
 
void enter ()
 Entering the critical section from level 0.
 
void leave ()
 Leaving the critical section.
 
void relay (Gate *item)
 A prologue wants its epilogue to be processed (entering from level 1).
 

Constants

PerCore< PerCoreQueue< Gate > > epilogue_queue
 Queue for Gates.
 
static Spinlock global_lock
 
static PerCore< int > core_lock (0)
 

Detailed Description

Synchronizes the kernel with interrupts using the Prologue/Epilogue Model.

The Guard is used to synchronize between "normal" core activities (currently just the text output, later system calls) and interrupt handling routines. For this purpose, Queue Guard::epilogue_queue provides Guard with a queue for each Core, in which gate objects can be added. This is necessary if the critical section is occupied at the time an interrupt occurs, and the epilogue() method cannot be executed immediately. The queued epilogues are processed when leaving the critical section.

Hints:

  • The epilogue queue is a central data structure, whose consistency must be ensured. The implementation provided by the Queue may be not interrupt-transparent. In theory, you could fix that by implemening a perfectly interrupt-transparent queue yourself, which is, however, very hard. The simplest solution is to just disable interrupts during operations on the queue (i.e., use hard synchronization).

  • In MPStuBS, you need a separate epilogue queue for each core, in which each processor serializes its epilogues. However, epilogues on different cores could then be executed in parallel, since the critical section is managed separately on a per-core base. This must be prevented by using a global Spinlock to avoid concurrent execution of epilogues – there must never be more than one epilogue active on the whole system at the same time!
    Please note: This giant lock (synchronizing all cores) should not be confused with the (core-specific) flag variable that marks only the entry to the epilogue level on the corresponding core!

  • Gate objects must not be enqueued multiple times in the same queue. So if two interrupts of the same type occur so quick (for MPStuBS: on the same core) that the corresponding epilogue has not yet been handled, you must not enqueue the same gate object again. The enqueue methods should prevent this.

  • Interrupts should be disabled for as short as possible. Due to this reason, the prologue/epilogue model allows epilogues to be interrupted by prologues. This means that interrupts should be enabled again before the epilogue is executed (this includes notifying the APIC about the End-Of-Interrupt)

Function Documentation

◆ active()

bool Guard::active ( )

Helper to check if we are currently in a guarded environment on this CPU core.

Returns
true if this CPU core is in epilogue level
Optional:
Implement for debugging purposes

◆ enter()

void Guard::enter ( )

Entering the critical section from level 0.

Entering the critical section has to be handled differently depending on the system: In a single-core system it is sufficient to mark the entry by just setting a lock variable (since only one control flow can enter the critical section at the same time). However, as soon as there are multiple cores, this is no longer the case. If a core wants to enter the critical section while another core is already in there, it should (actively) wait in this method until the critical area is released again.

Todo:
Implement Method

◆ leave()

void Guard::leave ( )

Leaving the critical section.

Leaves the critical section and processes all remaining (enqueued) epilogues.

Todo:
Implement Method

◆ relay()

void Guard::relay ( Gate item)

A prologue wants its epilogue to be processed (entering from level 1).

This method is called by interrupt_handler if the previously executed Gate::prologue has returned true – indicating that it needs its epilogue to be executed as well. Whether this is done immediately or the epilogue just enqueued to the epilogue queue depends on whether the critical section on this Core is accessible or not.

Todo:
Implement Method

Constant Documentation

◆ epilogue_queue

PerCore<PerCoreQueue<Gate> > Guard::epilogue_queue

Queue for Gates.

While for OOStuBS a simple linked list is sufficient (by having a head pointer in this calls and extending Gate with a next pointer), for multi-core systems like MPStuBS it needs to be able to enqueue the same Gate item on each Core (up to Core::MAX) at the same time (a multi-queue, requiring a head pointer array member in this class and a next pointer array in Gate).

◆ global_lock

Spinlock Guard::global_lock
static

◆ core_lock

PerCore< int > Guard::core_lock(0) ( )
static