/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ #include "DrKernel.h" template DRDECLARECLASS(DrStringDictionary); DrResource::DrResource(DrResourceLevel level, DrString name, DrString locality, DrResourcePtr parent) { m_level = level; m_name = name; m_locality = locality; m_parent = parent; m_children = DrNew DrResourceList(); if (m_parent != DrNull) { m_parent->GetChildren()->Add(this); } } void DrResource::Discard() { m_parent = DrNull; if (m_children != DrNull) { int i; for (i=0; iSize(); ++i) { m_children[i]->Discard(); } } m_children = DrNull; } DrResourceLevel DrResource::GetLevel() { return m_level; } DrString DrResource::GetName() { return m_name; } DrString DrResource::GetLocality() { return m_locality; } DrResourcePtr DrResource::GetParent() { return m_parent; } DrResourceListRef DrResource::GetChildren() { return m_children; } bool DrResource::Contains(DrResourcePtr resource) { if (resource->GetLevel() > m_level) { return false; } else if (resource->GetLevel() == m_level) { return (resource == this); } else { return Contains(resource->GetParent()); } } DrUniverse::DrUniverse() { m_resourceLock = DrNew DrCritSec(); m_resourceAtLevel = DrNew RAArray(DRL_Cluster+1); int i; for (i=DRL_Core; i<=DRL_Cluster; ++i) { m_resourceAtLevel[i] = DrNew DrResourceList(); } m_resource = DrNew DrResourceDictionary(); } void DrUniverse::Discard() { int i; for (i=DRL_Core; i<=DRL_Cluster; ++i) { int j; for (j=0; jSize(); ++j) { m_resourceAtLevel[i][j]->Discard(); } m_resourceAtLevel[i] = DrNull; } m_resourceAtLevel = DrNull; m_resource = DrNull; } DrCritSecPtr DrUniverse::GetResourceLock() { return m_resourceLock; } void DrUniverse::AddResource(DrResourcePtr resource) { m_resourceAtLevel[resource->GetLevel()]->Add(resource); m_resource->Add(resource->GetName().GetString(), resource); } DrResourceListRef DrUniverse::GetResources(DrResourceLevel level) { return m_resourceAtLevel[level]; } DrResourcePtr DrUniverse::LookUpResource(DrNativeString name) { return LookUpResourceInternal(DrString(name)); } DrResourcePtr DrUniverse::LookUpResourceInternal(DrString name) { DrResourceRef resource; if (m_resource->TryGetValue(name.GetString(), resource)) { return resource; } else { return DrNull; } } DrAffinity::DrAffinity() { m_isHardConstraint = false; m_weight = 0; m_locality = DrNew DrResourceList(); } void DrAffinity::SetHardConstraint(bool isHardConstraint) { m_isHardConstraint = isHardConstraint; } bool DrAffinity::GetHardConstraint() { return m_isHardConstraint; } void DrAffinity::SetWeight(UINT64 weight) { m_weight = weight; } UINT64 DrAffinity::GetWeight() { return m_weight; } void DrAffinity::AddLocality(DrResourcePtr locality) { m_locality->Add(locality); } DrResourceListRef DrAffinity::GetLocalityArray() { return m_locality; } DrAffinityRef DrAffinityIntersector::IntersectHardConstraints(DrAffinityPtr existingConstraints, DrAffinityListRef newAffinities) { DrAffinityRef constraints = existingConstraints; int i; for (i=0; iSize(); ++i) { DrAffinityPtr a = newAffinities[i]; if (a->GetHardConstraint()) { if (constraints == DrNull) { constraints = DrNew DrAffinity(); constraints->SetHardConstraint(true); int j; for (j=0; jGetLocalityArray()->Size(); ++j) { constraints->GetLocalityArray()->Add(a->GetLocalityArray()[j]); } } else { int j = 0; while (jGetLocalityArray()->Size()) { DrResourcePtr c = constraints->GetLocalityArray()[j]; int k; for (k=0; kGetLocalityArray()->Size(); ++k) { DrResourcePtr r = a->GetLocalityArray()[k]; if (c->Contains(r) || r->Contains(c)) { if (r->GetLevel() < c->GetLevel()) { /* narrow the constraint */ constraints->GetLocalityArray()[j] = r; } break; } } if (k == a->GetLocalityArray()->Size()) { /* we can't keep this constraint */ constraints->GetLocalityArray()->RemoveAt(j); } else { ++j; } } } } } return constraints; } DrAffinityMerger::DrAffinityMerger() { m_dictionary = DrNew ResourceWeightDictionary(); } void DrAffinityMerger::AccumulateWeights(DrAffinityListRef affinityList) { int i; for (i=0; iSize(); ++i) { AccumulateWeights(affinityList[i]); } } void DrAffinityMerger::AccumulateWeights(DrAffinityPtr affinity) { DrAssert(affinity->GetHardConstraint() == false); DrResourceListRef list = affinity->GetLocalityArray(); int i; for (i=0; iSize(); ++i) { DrResourcePtr r = list[i]; do { UINT64 weight; if (m_dictionary->TryGetValue(r, weight)) { weight += affinity->GetWeight(); m_dictionary->Replace(r, weight); } else { m_dictionary->Add(r, affinity->GetWeight()); } /* also accumulate the coarser-level information */ r = r->GetParent(); } while (r != DrNull); } } DrAffinityListRef DrAffinityMerger::GetMergedAffinities(DrFloatArrayRef levelThreshold) { DrUINT64ArrayRef levelTotal = DrNew DrUINT64Array(DRL_Cluster + 1); int level; for (level = DRL_Core; level <= DRL_Cluster; ++level) { levelTotal[level] = 0; } ResourceWeightDictionary::DrEnumerator eSum = m_dictionary->GetDrEnumerator(); while (eSum.MoveNext()) { levelTotal[eSum.GetKey()->GetLevel()] += eSum.GetValue(); } for (level = DRL_Core; level <= DRL_Cluster; ++level) { levelTotal[level] = (UINT64) ((float) levelTotal[level] * levelThreshold[level]); } DrAffinityListRef l = DrNew DrAffinityList(); ResourceWeightDictionary::DrEnumerator eFilter = m_dictionary->GetDrEnumerator(); while (eFilter.MoveNext()) { DrResourcePtr resource = eFilter.GetKey(); UINT64 weight = eFilter.GetValue(); level = resource->GetLevel(); if (weight >= levelTotal[level]) { DrAffinityRef a = DrNew DrAffinity(); a->SetWeight(weight); a->AddLocality(resource); l->Add(a); } } return l; }