> > The code will be changed to:
> >
> >   if ((INT32)InternalWaitForSemaphore (Context->CpuCount) < 0) {
> >     return RETURN_ABORTED;
> >   }
> 
> I find this quite ugly. In the "semaphore post" operation, we already
> have code that prevents incrementing if the semaphore is "locked". Can
> we perhaps create a "semaphore pend" operation that does the same?
> 
> How about this:
> 
> diff --git a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> index 3c2835f8def6..5d7fc58ef23f 100644
> --- a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> +++ b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> @@ -91,35 +91,38 @@ UINT32
>  InternalWaitForSemaphore (
>    IN OUT  volatile UINT32  *Sem
>    )
>  {
>    UINT32  Value;
> 
>    for ( ; ;) {
>      Value = *Sem;
> +    if (Value == MAX_UINT32) {
> +      return Value;
> +    }
>      if ((Value != 0) &&
>          (InterlockedCompareExchange32 (
>             (UINT32 *)Sem,
>             Value,
>             Value - 1
>             ) == Value))
>      {
>        break;
>      }
> 
>      CpuPause ();
>    }
> 
>    return Value - 1;
>  }
> 
> Note, I'm just brainstorming here, I've not thought it through. Just to
> illustrate the direction I'm thinking of.
> 
> This change should be mostly OK. InternalWaitForSemaphore() returns the
> decremented value. So, for InternalWaitForSemaphore() to return
> MAX_UINT32 *without* this update, the function would have to decrement
> the semaphore when the semaphore is zero. But in that case, the function
> *blocks*. Thus, a return value of MAX_UINT32 is not possible without
> this extension; ergo, if MAX_UINT32 is returned (with this extension),

Yes, that's for the semaphore sync usage, we have to block the sem if it's 
zero, decrease it when return. That's why I said - it's naturally make sure the 
Run is reset after all ready to exit.  Then it can achieve the below flow:
    BSP: ReleaseOneAp  -->  AP: WaitForBsp
    BSP: WaitForAPs    <--  AP: ReleaseBsp


For locked case, I just copy the existing logic from SMM cpu driver (as I 
document in the commit message: The instance refers the existing SMM CPU driver 
(PiSmmCpuDxeSmm) sync implementation and behavior):
existing ReleaseSemaphore() prevents increase the semaphore, but it still 
return the original semaphore value +1; --> that's why we have to check the 
return value is  0 or not in SmmCpuSyncCheckInCpu()
existing WaitForSemaphore() allow decrease the semaphore if locked, and it also 
return the original semaphore value -1;  --> that's why we have to check the 
return value is  < 0 or not in SmmCpuSyncCheckOutCpu()
 
so, do you want to align the behavior as below?

ReleaseSemaphore() prevents increase the semaphore if locked, and it should 
return the locked value (MAX_UINT32);  --> then we can check the return value 
is  MAX_UINT32 or not in SmmCpuSyncCheckInCpu(), and sem itself won't be 
changed.
WaitForSemaphore() prevents decrease the semaphore if locked, and it should 
return the locked value (MAX_UINT32); --> then we can check the return value is 
 MAX_UINT32 or not in SmmCpuSyncCheckOutCpu (), and sem itself won't be changed.

I think:
for ReleaseSemaphore, it must meet below 2 cases usage:
1. for semaphore sync usage (Run), it doesn't care the lock case, and returned 
value is not cared. Just check the semaphore itself.
2. for Rendezvous case (Counter), it not only needs to check locked or not from 
return value, but also require "only increase the semaphore if not locked".

for WaitForSemaphore, it must meet below 2 cases usage:
1. for semaphore sync usage (Run), it doesn't care the lock case, and returned 
value is not cared. But for the semaphore itself, it need block at 0, and 
decrease when return.
2. for Rendezvous case (Counter), it only needs to check locked or not from 
return value. semaphore itself is not cared.

So, based on above, I think, yes, we can do the change to align the lock 
behavior:  

/**
  Performs an atomic compare exchange operation to get semaphore.
  The compare exchange operation must be performed using MP safe
  mechanisms.

  @param[in,out]  Sem    IN:  32-bit unsigned integer
                         OUT: original integer - 1 if Sem is not locked.
                         OUT: original integer (MAX_UINT32) if Sem is locked.

  @retval     Original integer - 1 if Sem is not locked.
              Original integer (MAX_UINT32) if Sem is locked.

**/
STATIC
UINT32
InternalWaitForSemaphore (
  IN OUT  volatile UINT32  *Sem
  )
{
  UINT32  Value;

  for ( ; ;) {
    Value = *Sem;
    if (Value == MAX_UINT32) {
      return Value;
    }

    if ((Value != 0) &&
        (InterlockedCompareExchange32 (
           (UINT32 *)Sem,
           Value,
           Value - 1
           ) == Value))
    {
      break;
    }

    CpuPause ();
  }

  return Value - 1;
}

/**
  Performs an atomic compare exchange operation to release semaphore.
  The compare exchange operation must be performed using MP safe
  mechanisms.

  @param[in,out]  Sem    IN:  32-bit unsigned integer
                         OUT: original integer + 1 if Sem is not locked.
                         OUT: original integer (MAX_UINT32) if Sem is locked.

  @retval    Original integer + 1 if Sem is not locked.
             Original integer (MAX_UINT32) if Sem is locked.

**/
STATIC
UINT32
InternalReleaseSemaphore (
  IN OUT  volatile UINT32  *Sem
  )
{
  UINT32  Value;

  do {
    Value = *Sem;
  } while (Value + 1 != 0 &&
           InterlockedCompareExchange32 (
             (UINT32 *)Sem,
             Value,
             Value + 1
             ) != Value);

  if (Value == MAX_UINT32) {
    return Value;
  }

  return Value + 1;
}

I haven't see any issue with this change. 

> we know the door was locked earlier (and the semaphore is not changed).
> 
> At the same time, we might want to update InternalReleaseSemaphore() as
> well, so that it cannot validly increment the semaphore value to MAX_UINT32.
> 
> 
> 
> >
> >



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#112542): https://edk2.groups.io/g/devel/message/112542
Mute This Topic: https://groups.io/mt/103010165/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to