mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 13:35:48 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			387 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
  
 | 
						|
  timer.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  EFI Event support
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
 | 
						|
#include <DxeMain.h>
 | 
						|
 | 
						|
//
 | 
						|
// Internal prototypes
 | 
						|
//
 | 
						|
STATIC
 | 
						|
UINT64
 | 
						|
CoreCurrentSystemTime (
 | 
						|
  VOID
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CoreCheckTimers (
 | 
						|
  IN EFI_EVENT    Event,
 | 
						|
  IN VOID         *Context
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
CoreInsertEventTimer (
 | 
						|
  IN IEVENT       *Event
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Internal data
 | 
						|
//
 | 
						|
 | 
						|
static LIST_ENTRY       mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
 | 
						|
static EFI_LOCK         mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL - 1);
 | 
						|
static EFI_EVENT        mEfiCheckTimerEvent;
 | 
						|
 | 
						|
static EFI_LOCK         mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
 | 
						|
static UINT64           mEfiSystemTime = 0;
 | 
						|
 | 
						|
//
 | 
						|
// Timer functions
 | 
						|
//
 | 
						|
 | 
						|
VOID
 | 
						|
CoreInitializeTimer (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initializes timer support
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = CoreCreateEvent (
 | 
						|
              EFI_EVENT_NOTIFY_SIGNAL,
 | 
						|
              EFI_TPL_HIGH_LEVEL - 1,
 | 
						|
              CoreCheckTimers,
 | 
						|
              NULL,
 | 
						|
              &mEfiCheckTimerEvent
 | 
						|
              );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
UINT64
 | 
						|
CoreCurrentSystemTime (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Returns the current system time
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  Returns the current system time
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT64          SystemTime;
 | 
						|
 | 
						|
  CoreAcquireLock (&mEfiSystemTimeLock);
 | 
						|
  SystemTime = mEfiSystemTime;
 | 
						|
  CoreReleaseLock (&mEfiSystemTimeLock);
 | 
						|
  return SystemTime;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CoreTimerTick (
 | 
						|
  IN UINT64   Duration
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Called by the platform code to process a tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Duration    - The number of 100ns elasped since the last call to TimerTick
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  IEVENT          *Event;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check runtiem flag in case there are ticks while exiting boot services
 | 
						|
  //
 | 
						|
 | 
						|
  CoreAcquireLock (&mEfiSystemTimeLock);
 | 
						|
 | 
						|
  //
 | 
						|
  // Update the system time
 | 
						|
  //
 | 
						|
 | 
						|
  mEfiSystemTime += Duration;
 | 
						|
 | 
						|
  //
 | 
						|
  // If the head of the list is expired, fire the timer event
 | 
						|
  // to process it
 | 
						|
  //
 | 
						|
 | 
						|
  if (!IsListEmpty (&mEfiTimerList)) {
 | 
						|
    Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
 | 
						|
 | 
						|
    if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {
 | 
						|
      CoreSignalEvent (mEfiCheckTimerEvent);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CoreReleaseLock (&mEfiSystemTimeLock);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CoreCheckTimers (
 | 
						|
  IN EFI_EVENT            CheckEvent,
 | 
						|
  IN VOID                 *Context
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Checks the sorted timer list against the current system time.
 | 
						|
  Signals any expired event timer.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  CheckEvent  - Not used
 | 
						|
 | 
						|
  Context     - Not used
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT64                  SystemTime;
 | 
						|
  IEVENT                  *Event;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the timer database for expired timers
 | 
						|
  //
 | 
						|
 | 
						|
  CoreAcquireLock (&mEfiTimerLock);
 | 
						|
  SystemTime = CoreCurrentSystemTime ();
 | 
						|
 | 
						|
  while (!IsListEmpty (&mEfiTimerList)) {
 | 
						|
    Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
 | 
						|
 | 
						|
    //
 | 
						|
    // If this timer is not expired, then we're done
 | 
						|
    //
 | 
						|
 | 
						|
    if (Event->u.Timer.TriggerTime > SystemTime) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Remove this timer from the timer queue
 | 
						|
    //
 | 
						|
 | 
						|
    RemoveEntryList (&Event->u.Timer.Link);
 | 
						|
    Event->u.Timer.Link.ForwardLink = NULL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Signal it
 | 
						|
    //
 | 
						|
    CoreSignalEvent (Event);
 | 
						|
 | 
						|
    //
 | 
						|
    // If this is a periodic timer, set it
 | 
						|
    //
 | 
						|
    if (Event->u.Timer.Period) {
 | 
						|
 | 
						|
      //
 | 
						|
      // Compute the timers new trigger time
 | 
						|
      //
 | 
						|
 | 
						|
      Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;
 | 
						|
 | 
						|
      //
 | 
						|
      // If that's before now, then reset the timer to start from now
 | 
						|
      //
 | 
						|
      if (Event->u.Timer.TriggerTime <= SystemTime) {
 | 
						|
        Event->u.Timer.TriggerTime = SystemTime;
 | 
						|
        CoreSignalEvent (mEfiCheckTimerEvent);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the timer
 | 
						|
      //
 | 
						|
 | 
						|
      CoreInsertEventTimer (Event);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CoreReleaseLock (&mEfiTimerLock);
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
CoreInsertEventTimer (
 | 
						|
  IN IEVENT   *Event
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Inserts the timer event
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Event - Points to the internal structure of timer event to be installed
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT64          TriggerTime;
 | 
						|
  LIST_ENTRY      *Link;
 | 
						|
  IEVENT          *Event2;
 | 
						|
 | 
						|
  ASSERT_LOCKED (&mEfiTimerLock);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the timer's trigger time
 | 
						|
  //
 | 
						|
 | 
						|
  TriggerTime = Event->u.Timer.TriggerTime;
 | 
						|
 | 
						|
  //
 | 
						|
  // Insert the timer into the timer database in assending sorted order
 | 
						|
  //
 | 
						|
 | 
						|
  for (Link = mEfiTimerList.ForwardLink; Link  != &mEfiTimerList; Link = Link->ForwardLink) {
 | 
						|
    Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
 | 
						|
 | 
						|
    if (Event2->u.Timer.TriggerTime > TriggerTime) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  InsertTailList (Link, &Event->u.Timer.Link);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreSetTimer (
 | 
						|
  IN EFI_EVENT            UserEvent,
 | 
						|
  IN EFI_TIMER_DELAY      Type,
 | 
						|
  IN UINT64               TriggerTime
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Sets the type of timer and the trigger time for a timer event.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserEvent   - The timer event that is to be signaled at the specified time
 | 
						|
  Type        - The type of time that is specified in TriggerTime
 | 
						|
  TriggerTime - The number of 100ns units until the timer expires
 | 
						|
  
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS           - The event has been set to be signaled at the requested time
 | 
						|
  EFI_INVALID_PARAMETER - Event or Type is not valid
 | 
						|
 | 
						|
--*/  
 | 
						|
{
 | 
						|
  IEVENT      *Event;
 | 
						|
  
 | 
						|
  Event = UserEvent;
 | 
						|
 | 
						|
  if (Event == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Event->Signature != EVENT_SIGNATURE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Type < 0 || Type > TimerRelative  || !(Event->Type & EFI_EVENT_TIMER)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 
 | 
						|
  CoreAcquireLock (&mEfiTimerLock);
 | 
						|
 | 
						|
  //
 | 
						|
  // If the timer is queued to the timer database, remove it
 | 
						|
  //
 | 
						|
 | 
						|
  if (Event->u.Timer.Link.ForwardLink != NULL) {
 | 
						|
    RemoveEntryList (&Event->u.Timer.Link);
 | 
						|
    Event->u.Timer.Link.ForwardLink = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Event->u.Timer.TriggerTime = 0;
 | 
						|
  Event->u.Timer.Period = 0;
 | 
						|
 | 
						|
  if (Type != TimerCancel) {
 | 
						|
 | 
						|
    if (Type == TimerPeriodic) {
 | 
						|
      Event->u.Timer.Period = TriggerTime;
 | 
						|
    }
 | 
						|
 | 
						|
    Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
 | 
						|
    CoreInsertEventTimer (Event);
 | 
						|
 | 
						|
    if (TriggerTime == 0) {
 | 
						|
      CoreSignalEvent (mEfiCheckTimerEvent);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CoreReleaseLock (&mEfiTimerLock);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |