📄 schedulingring.cpp
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// SchedulingRing.cpp
//
// Source file containing the SchedulingRing implementation.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "concrtinternal.h"
namespace Concurrency
{
namespace details
{
/// <summary>
/// Construct a new scheduling ring.
/// </summary>
SchedulingRing::SchedulingRing(SchedulerBase *pScheduler, int id) :
m_pScheduler(pScheduler),
m_pNode(NULL), // Will be set later explicitly by the creating scheduler
m_pAnonymousScheduleGroup(NULL),
m_id(id),
m_nextGroup(0),
m_scheduleGroups(pScheduler, 256, 64)
{
//
// Create the anonymous schedule group early. UMS schedulers need somewhere to begin a search for a given node that is guaranteed
// to be safe. This is the only such place.
//
// Create schedule group takes a reference to the schedule group. The scheduling
// node maintains this reference and will release it when it disassociates from the
// schedule group (either in the destructor, or if the schedule group is moved to
// a different node due to resource management reclaiming the node).
//
m_pAnonymousScheduleGroup = CreateScheduleGroup();
// An anonymous SG, once created lives for the lifetime of the scheduler.
m_pAnonymousScheduleGroup->m_kind |= ScheduleGroupBase::AnonymousScheduleGroup;
}
SchedulingRing::~SchedulingRing()
{
ASSERT(m_pAnonymousScheduleGroup != NULL);
m_pAnonymousScheduleGroup->m_kind &= ~ScheduleGroupBase::AnonymousScheduleGroup;
m_pAnonymousScheduleGroup->InternalRelease();
m_pAnonymousScheduleGroup = NULL;
}
ScheduleGroupBase *SchedulingRing::AllocateScheduleGroup()
{
if (m_pScheduler->m_schedulingProtocol == ::Concurrency::EnhanceScheduleGroupLocality)
{
return new CacheLocalScheduleGroup(this);
}
else
{
ASSERT(m_pScheduler->m_schedulingProtocol == ::Concurrency::EnhanceForwardProgress);
return new FairScheduleGroup(this);
}
}
#pragma warning(disable:25007) // method can be static
void SchedulingRing::FreeScheduleGroup(ScheduleGroupBase *pGroup)
{
delete pGroup;
}
#pragma warning(default:25007) // method can be static
ScheduleGroupBase *SchedulingRing::CreateScheduleGroup()
{
ScheduleGroupBase* pGroup = m_scheduleGroups.PullFromFreePool();
if (pGroup == NULL)
{
pGroup = AllocateScheduleGroup();
}
else
{
// reinitialize the reused schedule group to its initial state
ASSERT(pGroup->m_refCount == 0);
pGroup->m_refCount = 1;
pGroup->m_pRing = this;
}
m_scheduleGroups.Add(pGroup);
SetPseudoRRScheduleGroup(m_nextGroup);
ASSERT(pGroup->m_refCount >= 0);
return pGroup;
}
//
// Called when a schedule group's ref count is 0. remove this schedule group from the action.
//
void SchedulingRing::RemoveScheduleGroup(ScheduleGroupBase *pGroup)
{
//
// Essentially m_refCount is the refcount of how many contexts reference this schedule group.
// m_refCount is incremented whenever a schedule group is associated with a context, decremented
// when a context is switched out to another context. When workstealing happens the context that
// steals from this schedule group increments m_refCount and decrements after it is done with this
// schedule group, whether by stealing from another or by switching out and going back on the
// freelist. When m_refCount hits 0, then the schedule group is taken out of m_groups and hence
// is not searched for runnables or stolen chores.
//
ASSERT(pGroup != NULL && pGroup->m_refCount == 0);
// It is still in the circular list, but other apis that are traversing the list will move over
// it, since it will not have any runnable contexts or chores to steal.
m_scheduleGroups.Remove(pGroup);
}
ScheduleGroupBase *SchedulingRing::GetAnonymousScheduleGroup()
{
ASSERT(m_pAnonymousScheduleGroup != NULL);
return m_pAnonymousScheduleGroup;
}
} // namespace details
} // namespace Concurrency
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -