Understanding Execution level priority


Kumar G <kumarg27061979@...>
 

Many Thanks Andrew
Clear now
Regards
Kumar

On Thu, 15 Sept 2022 at 04:59, Andrew Fish <afish@...> wrote:



On Sep 14, 2022, at 2:53 AM, Kumar G <kumarg27061979@...> wrote:

Many Thanks for reply Andrew,

Sorry it brings a couple of questions. may be stupid questions

There are not 2 executions contexts there is only one. UEFI is a
cooperative event model.
So running at a given TPL prevents any code at that TPL or lower from
running.
If you put a while(TRUE); loop at an elevated TPL the main flow of
execution will never run again.

Under the hood the events are registered into a queue and that queue is
dispatched when calling gBS->RestoreTPL() [1].
Given the cooperative model the “locks” that prevent preemption are
really just calls to gBS->RaiseTPL().

Makes sense since you block any code at the TPL you raised to or lower
from running.
The timer tick is going to gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR,
and the DXE Core will gBS->RaiseTPL()/gBS->RestoreTPL()

I see only timer ISR can break a loop, if while(TRUE) loop is running at
low priority. and processes the events.

If running this while(TRUE) is at high priority then, impact of timer ISR
calling gBS->RestoreTPL will be ignored.


Kumar,

Yes this is kind of the definition of cooperative. No cooperation ==
deadlock. If you notice the UEFI Spec claims the TPL_HIGH_LEVEL is reserved
for the system firmware.

There is no need for an UEFI driver to do interrupt handling, and there
are no platform abstractions to implement it. This is why only the system
firmware needs TPL_HIGH_LEVEL. Generic UEFI drivers are going to use a
timer event to poll the device.

If you are sitting at the UEFI Shell prompt then you are mostly are
stalling in an event loop via calling gBS->WaitForEvent().

Correct me, here we have two contexts from where gBS->RestoreTPL() can be
called , First is timer ISR and second is
DXE core (or say main thread)


Technically speaking events could raise/restore TPL too as they are
dispatched to prevent preemption.

This brings another question, in UEFI events can not be 100% synchronous ,
correct ?
NotifyEvent function will just queue the event, and in next call i.e
gBS->RestoreTPL() event handler can be notified


Yes the events are queued. An event model implies and event loop, also
called work loop, style of programming. See [1].

You have to think differently than threading and break stuff up so you
don’t spend lots of time in events.

[1] https://berb.github.io/diploma-thesis/original/043_threadsevents.html

Thanks,

Andrew Fish


around the handle services to protect the handle/protocol database from
getting corrupted by preemption.


On Tue, 13 Sept 2022 at 23:56, Andrew Fish <afish@...> wrote:



On Sep 6, 2022, at 10:53 PM, Kumar G <kumarg27061979@...> wrote:

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something


There are not 2 executions contexts there is only one. UEFI is a
cooperative event model. So running at a given TPL prevents any code at
that TPL or lower from running. If you put a while(TRUE); loop at an
elevated TPL the main flow of execution will never run again.

Under the hood the events are registered into a queue and that queue is
dispatched when calling gBS->RestoreTPL() [1]. Given the cooperative model
the “locks” that prevent preemption are really just calls to
gBS->RaiseTPL(). Makes sense since you block any code at the TPL you raised
to or lower from running. The timer tick is going to
gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR, and the DXE Core will
gBS->RaiseTPL()/gBS->RestoreTPL() around the handle services to protect the
handle/protocol database from getting corrupted by preemption.

[1]
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Tpl.c#L122

Thanks,

Andrew Fish

Thanks in advance

Regards
Kumar G







Andrew Fish
 

On Sep 14, 2022, at 2:53 AM, Kumar G <kumarg27061979@...> wrote:

Many Thanks for reply Andrew,

Sorry it brings a couple of questions. may be stupid questions

There are not 2 executions contexts there is only one. UEFI is a cooperative event model.
So running at a given TPL prevents any code at that TPL or lower from running.
If you put a while(TRUE); loop at an elevated TPL the main flow of execution will never run again.
Under the hood the events are registered into a queue and that queue is dispatched when calling gBS->RestoreTPL() [1].
Given the cooperative model the “locks” that prevent preemption are really just calls to gBS->RaiseTPL().
Makes sense since you block any code at the TPL you raised to or lower from running.
The timer tick is going to gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR, and the DXE Core will gBS->RaiseTPL()/gBS->RestoreTPL()
I see only timer ISR can break a loop, if while(TRUE) loop is running at low priority. and processes the events.

If running this while(TRUE) is at high priority then, impact of timer ISR calling gBS->RestoreTPL will be ignored.
Kumar,

Yes this is kind of the definition of cooperative. No cooperation == deadlock. If you notice the UEFI Spec claims the TPL_HIGH_LEVEL is reserved for the system firmware.

There is no need for an UEFI driver to do interrupt handling, and there are no platform abstractions to implement it. This is why only the system firmware needs TPL_HIGH_LEVEL. Generic UEFI drivers are going to use a timer event to poll the device.

If you are sitting at the UEFI Shell prompt then you are mostly are stalling in an event loop via calling gBS->WaitForEvent().

Correct me, here we have two contexts from where gBS->RestoreTPL() can be called , First is timer ISR and second is
DXE core (or say main thread)
Technically speaking events could raise/restore TPL too as they are dispatched to prevent preemption.

This brings another question, in UEFI events can not be 100% synchronous , correct ?
NotifyEvent function will just queue the event, and in next call i.e gBS->RestoreTPL() event handler can be notified
Yes the events are queued. An event model implies and event loop, also called work loop, style of programming. See [1].

You have to think differently than threading and break stuff up so you don’t spend lots of time in events.

[1] https://berb.github.io/diploma-thesis/original/043_threadsevents.html

Thanks,

Andrew Fish


around the handle services to protect the handle/protocol database from getting corrupted by preemption.

On Tue, 13 Sept 2022 at 23:56, Andrew Fish <afish@... <mailto:afish@...>> wrote:


On Sep 6, 2022, at 10:53 PM, Kumar G <kumarg27061979@... <mailto:kumarg27061979@...>> wrote:

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something
There are not 2 executions contexts there is only one. UEFI is a cooperative event model. So running at a given TPL prevents any code at that TPL or lower from running. If you put a while(TRUE); loop at an elevated TPL the main flow of execution will never run again.

Under the hood the events are registered into a queue and that queue is dispatched when calling gBS->RestoreTPL() [1]. Given the cooperative model the “locks” that prevent preemption are really just calls to gBS->RaiseTPL(). Makes sense since you block any code at the TPL you raised to or lower from running. The timer tick is going to gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR, and the DXE Core will gBS->RaiseTPL()/gBS->RestoreTPL() around the handle services to protect the handle/protocol database from getting corrupted by preemption.

[1] https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Tpl.c#L122

Thanks,

Andrew Fish

Thanks in advance

Regards
Kumar G





Kumar G <kumarg27061979@...>
 

Many Thanks for reply Andrew,

Sorry it brings a couple of questions. may be stupid questions

There are not 2 executions contexts there is only one. UEFI is a
cooperative event model.
So running at a given TPL prevents any code at that TPL or lower from
running.
If you put a while(TRUE); loop at an elevated TPL the main flow of
execution will never run again.

Under the hood the events are registered into a queue and that queue is
dispatched when calling gBS->RestoreTPL() [1].
Given the cooperative model the “locks” that prevent preemption are
really just calls to gBS->RaiseTPL().

Makes sense since you block any code at the TPL you raised to or lower
from running.
The timer tick is going to gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR,
and the DXE Core will gBS->RaiseTPL()/gBS->RestoreTPL()

I see only timer ISR can break a loop, if while(TRUE) loop is running at
low priority. and processes the events.

If running this while(TRUE) is at high priority then, impact of timer ISR
calling gBS->RestoreTPL will be ignored.

Correct me, here we have two contexts from where gBS->RestoreTPL() can be
called , First is timer ISR and second is
DXE core (or say main thread)

This brings another question, in UEFI events can not be 100% synchronous ,
correct ?
NotifyEvent function will just queue the event, and in next call i.e
gBS->RestoreTPL() event handler can be notified


around the handle services to protect the handle/protocol database from
getting corrupted by preemption.


On Tue, 13 Sept 2022 at 23:56, Andrew Fish <afish@...> wrote:



On Sep 6, 2022, at 10:53 PM, Kumar G <kumarg27061979@...> wrote:

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something


There are not 2 executions contexts there is only one. UEFI is a
cooperative event model. So running at a given TPL prevents any code at
that TPL or lower from running. If you put a while(TRUE); loop at an
elevated TPL the main flow of execution will never run again.

Under the hood the events are registered into a queue and that queue is
dispatched when calling gBS->RestoreTPL() [1]. Given the cooperative model
the “locks” that prevent preemption are really just calls to
gBS->RaiseTPL(). Makes sense since you block any code at the TPL you raised
to or lower from running. The timer tick is going to
gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR, and the DXE Core will
gBS->RaiseTPL()/gBS->RestoreTPL() around the handle services to protect the
handle/protocol database from getting corrupted by preemption.

[1]
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Tpl.c#L122

Thanks,

Andrew Fish

Thanks in advance

Regards
Kumar G







Andrew Fish
 

On Sep 6, 2022, at 10:53 PM, Kumar G <kumarg27061979@...> wrote:

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something
There are not 2 executions contexts there is only one. UEFI is a cooperative event model. So running at a given TPL prevents any code at that TPL or lower from running. If you put a while(TRUE); loop at an elevated TPL the main flow of execution will never run again.

Under the hood the events are registered into a queue and that queue is dispatched when calling gBS->RestoreTPL() [1]. Given the cooperative model the “locks” that prevent preemption are really just calls to gBS->RaiseTPL(). Makes sense since you block any code at the TPL you raised to or lower from running. The timer tick is going to gBS->RaiseTPL()/gBS->RestoreTPL() in the ISR, and the DXE Core will gBS->RaiseTPL()/gBS->RestoreTPL() around the handle services to protect the handle/protocol database from getting corrupted by preemption.

[1] https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Tpl.c#L122

Thanks,

Andrew Fish

Thanks in advance

Regards
Kumar G





Kumar G <kumarg27061979@...>
 

Kindly help here please
Regards
Kumar G

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something

Thanks in advance

Regards
Kumar G


Kumar G <kumarg27061979@...>
 

Hi Experts,
I am trying to understand UEFI task priority

UEFI documentation says there are three levels of
execution TPL_APPLICATION, TPL_CALLBACK and TPL_NOTIFY.

What I understood there are two execution contexts
1) Main thread
2) Under timer interrupt.

Could someone help, how three level of task level priority is possible,
when there are two execution context,
or I missed something

Thanks in advance

Regards
Kumar G