Random and tl;dr fun friday fact. You can see the efi locks replaced w/ spinlocks in https://github.com/tianocore/edk2-staging/tree/MpNetworkStack to support the use case described in https://uefi.org/sites/default/files/resources/7_Maciej%20Vincent_INTEL_network%20stack%20performance.pdf. These changes along w/ a bespoke threading protocol allow for running efi networking code across all cores and still be able to interact w/ an enlightened dxe core. We didn't push forward to standardize for various reasons, such as folks pursuing an alternate solution to the original problem statement (e.g., LinuxBoot for datacenter network provisioning) and the huge legacy app compat we'd face. So it's 'possible', just as you 'could' have i/o device interrupt service routines (isr) w/ their own 'device' tpl's between notify and high (see "firmware interrupts" https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#tpl-usage) if you were to expose the appropriate registration and dispatch interface from the core. I don't think we put anything in staging or elsewhere public w/ isr examples, though, and I expect trying to retrofit after 2+ decades would face similar app compat issues w/ folks who already curate their own proprietary device interrupt sol'n. Vincent
On Fri, May 5, 2023 at 12:59 PM Laszlo Ersek <ler...@redhat.com> wrote: > > Hi Andrew, > > thank you! The background / paragraph on the naming helps! > > Cheers, > Laszlo > > On 5/4/23 20:01, Andrew (EFI) Fish wrote: > > Laszlo, > > > > Hope you are doing well! Sorry to top post but I’m just commenting on > > the big picture, not answering your specific questions yet. > > > > The Wiki definition of lock is something like: In computer science > > locks are a mechanism that enforces limits on access to a resource when > > there is the possibility for contention between threads of execution. I > > think the key point here is “threads of execution” is not threads…. > > > > UEFI is single threaded with a cooperative event model. There is no > > scheduler and an event blocks all forward progress of any event at the > > same or lower TPL. The protocol services have defined TPL Restrictions > > [1] so that is possible to implement locking. In the context of EFI > > raising the TPL blocks any “threads of execution” (events) that could > > preempt the running code from contending with a critical section. > > > > Lets thing about what would happen if you use an atomic primitive as a > > lock in EFI. Let’s say the app is installing a protocol so the DXE Core > > has the protocol database locked. Any event that fired in that window > > would not be able to call any UEFI Boot Service that was related to > > protocols and expect it to succeed. If the event blocked on the lock, > > the system is dead locked. If the the lock was tested and failed that > > basically means it would be normal for any UEFI service to fail in > > events and event code needed to coded to deal with that. Basically the > > even could we need to defer to a future time the event gets signaled. I > > think think this quickly devolves in the event code having to implement > > a simple scheduler for its set. Thus making locks raise the TPL is just > > better for everyone. > > > > Not that we have always been good at naming things, but in the context > > of EFI a Lock is best implemented as raising TPL so we made an up level > > look API to make that clear to people, and to help educate people how > > locks should be implemented in EFI. > > > > This is old, but it is a good sumarry of why we did not want BIOS > > programmers dealing with threads 20+ years ago when we designed EFI. > > > > > > preview.png > > threads <https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf> > > PDF Document · 107 KB > > <https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf> > > > > <https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf> > > > > > > [1] > > https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#tpl-restrictions > > > > <https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#tpl-restrictions> > > > > Thanks, > > > > Andrew Fish > > > >> On May 4, 2023, at 1:45 AM, Laszlo Ersek <ler...@redhat.com> wrote: > >> > >> Hi, > >> > >> what benefit does EFI_LOCK add, over direct gBS->RaiseTPL() and > >> gBS->RestoreTPL() calls? > >> > >> Considering just the two APIs EfiAcquireLock() and EfiReleaseLock(): > >> > >> - The "Lock" field (effectively, lock status field) is useless; it is > >> only written to, never read (outside of ASSERT()s) > >> > >> - The "OwnerTpl" and "Tpl" fields are just convenience storage for the > >> new TPL we raise to, and the old TPL we restore. > >> > >> Considering the EfiAcquireLockOrFail() API as well: > >> > >> - This does read the "Lock" (lock status) field, and if it is > >> EfiLockAcquired, the RaiseTPL() call is refused. So the idea here seems > >> to be to ensure a *strict* rise in the TPL. Namely, the RaiseTPL() in > >> EfiAcquireLockOrFail() would still succeed after the RaiseTPL() in > >> EfiAcquireLock() -- it is valid to "raise" the TPL to the current TPL > >> --, but the lock status check prevents that. > >> > >> - However (#1), this same "strict" raise would be possible by just > >> calling RaiseTPL() again, and comparing the returned old TPL against the > >> TPL we've just set as new. If the old TPL is strictly lower, then we've > >> just "acquired the lock", otherwise we've "already been holding" the > >> lock. So, from this perspective, EfiAcquireLockOrFail() doesn't add much. > >> > >> - Furthermore (#2), if another agent raised the TPL already, but didn't > >> use our particlar EFI_LOCK object to do that, then the status stored in > >> "EFI_LOCK.Lock" will not be able to track anything. > >> > >> So what is EFI_LOCK good for? > >> > >> Effectively I'm disturbed by the *name* "EFI_LOCK". A lock (or mutex) is > >> supposed to protect some shared resource. If two agents access the > >> resource without first acquiring the lock, there's trouble. Therefore > >> the resource itself becomes qualified as "requiring protection by the > >> lock, at all times". However, the "current TPL" is *not* a resource like > >> that. It's a UEFI spec level concept; the RaiseTPL and RestoreTPL boot > >> services are available to any agents; those agents are *not* required to > >> go through any kind of extra mutual exclusion. > >> > >> I've also considered that maybe EFI_LOCK could provide some protection > >> against inadvertently *lowering* the TPL via RaiseTPL() (which is > >> undefined behavior, per spec). But I don't see how -- > >> EfiAcquireLockOrFail() will happily lower the TPL if the Lock field is > >> EfiLockReleased, but another agent has meanwhile raised the TPL strictly > >> above the Tpl field. > >> > >> Please explain. :) > >> > >> Thanks! > >> Laszlo > >> > > > > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#104160): https://edk2.groups.io/g/devel/message/104160 Mute This Topic: https://groups.io/mt/98680041/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-