uefi CoreTimerTick

来源:互联网 发布:淘宝关闭店铺 重开 编辑:程序博客网 时间:2024/06/06 05:21
CoreTimerTick 是ueif的timer中断的处理函数,也是uefi中唯一支持的中断。
其路径在mdemodulepkg/core/dxe/event
CoreTimerTick (
  IN UINT64   Duration
  )
{
  IEVENT          *Event;

  CoreAcquireLock (&mEfiSystemTimeLock);


  mEfiSystemTime += Duration;

  if (!IsListEmpty (&mEfiTimerList)) {
    Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);

    if (Event->Timer.TriggerTime <= mEfiSystemTime) {
      CoreSignalEvent (mEfiCheckTimerEvent);
    }
  }

  CoreReleaseLock (&mEfiSystemTimeLock);
}
CoreTimerTick 中首先更新系统时间 mEfiSystemTime += Duration;通过下面方式的到系统时间的时候要加锁,
UINT64
CoreCurrentSystemTime (
  VOID
  )
{
  UINT64          SystemTime;

  CoreAcquireLock (&mEfiSystemTimeLock);
  SystemTime = mEfiSystemTime;
  CoreReleaseLock (&mEfiSystemTimeLock);

  return SystemTime;
}
就是因为会在中断函数CoreTimerTick 中更新这个值。
CoreTimerTick 中还有检测系统中定时器事件是否到期,如果到期的话就触发event函数CoreSignalEvent (mEfiCheckTimerEvent);
CoreSignalEvent (
  IN EFI_EVENT    UserEvent
  )
{
  IEVENT          *Event;

  Event = UserEvent;

  if (Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Event->Signature != EVENT_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  CoreAcquireEventLock ();

  //
  // If the event is not already signalled, do so
  //

  if (Event->SignalCount == 0x00000000) {
    Event->SignalCount++;

    //
    // If signalling type is a notify function, queue it
    //
    if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
      if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) {
        //
        // The CreateEventEx() style requires all members of the Event Group
        //  to be signaled.
        //
        CoreReleaseEventLock ();
        CoreNotifySignalList (&Event->EventGroup);
        CoreAcquireEventLock ();
       } else {
        CoreNotifyEvent (Event);
      }
    }
  }

  CoreReleaseEventLock ();
  return EFI_SUCCESS;
}
CoreSignalEvent 中会比较Event->Type & EVT_NOTIFY_SIGNAL ,如果不成立说明不需要发送event直接返回
如果成立的话还要判断Event->ExFlag & EVT_EXFLAG_EVENT_GROUP 也就是有没有设定event group ,如果设定的话
 就call       CoreNotifySignalList (&Event->EventGroup);
来判断Event->EventGroup 是否和mEfiCheckTimerEvent 的event group是否相等
VOID
CoreNotifySignalList (
  IN EFI_GUID     *EventGroup
  )
{
  LIST_ENTRY              *Link;
  LIST_ENTRY              *Head;
  IEVENT                  *Event;

  CoreAcquireEventLock ();

  Head = &gEventSignalQueue;
  for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
    Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
    if (CompareGuid (&Event->EventGroup, EventGroup)) {
      CoreNotifyEvent (Event);
    }
  }

  CoreReleaseEventLock ();
}
如果相等就调用CoreNotifyEvent来将这个event加入到gEventQueue 中,
VOID
CoreNotifyEvent (
  IN  IEVENT      *Event
  )
{

  //
  // Event database must be locked
  //
  ASSERT_LOCKED (&gEventQueueLock);

  //
  // If the event is queued somewhere, remove it
  //

  if (Event->NotifyLink.ForwardLink != NULL) {
    RemoveEntryList (&Event->NotifyLink);
    Event->NotifyLink.ForwardLink = NULL;
  }

  //
  // Queue the event to the pending notification list
  //

  InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
  gEventPending |= (UINTN)(1 << Event->NotifyTpl);
}
也就是这个时候其实并没有触发event,所以uefi里的timer event会在规定时候晚一点执行
具体是在CoreRestoreTpl ->CoreDispatchEventNotifies 才来触发event
在CoreRestoreTpl 中会按照Priority 来调用CoreDispatchEventNotifies。一个level的Priority执行完后在call下一个Priority

**/
VOID
CoreDispatchEventNotifies (
  IN EFI_TPL      Priority
  )
{
  IEVENT          *Event;
  LIST_ENTRY      *Head;

  CoreAcquireEventLock ();
  ASSERT (gEventQueueLock.OwnerTpl == Priority);
  Head = &gEventQueue[Priority];

  //
  // Dispatch all the pending notifications
  //
  while (!IsListEmpty (Head)) {

    Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
    RemoveEntryList (&Event->NotifyLink);

    Event->NotifyLink.ForwardLink = NULL;

    //
    // Only clear the SIGNAL status if it is a SIGNAL type event.
    // WAIT type events are only cleared in CheckEvent()
    //
    if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
      Event->SignalCount = 0;
    }

    CoreReleaseEventLock ();

    //
    // Notify this event
    //
    ASSERT (Event->NotifyFunction != NULL);
    Event->NotifyFunction (Event, Event->NotifyContext);

    //
    // Check for next pending event
    //
    CoreAcquireEventLock ();
  }

  gEventPending &= ~(UINTN)(1 << Priority);
  CoreReleaseEventLock ();
}

CoreDispatchEventNotifies 中就首先执行注册event的时候的NotifyFunction函数。Event->NotifyFunction (Event, Event->NotifyContext);
最后将这一个Priority 需要需要执行的pendingevent清零.  gEventPending &= ~(UINTN)(1 << Priority);

 
0 0
原创粉丝点击