singrdk/base/Kernel/Singularity/Scheduling/Robin/RobinActivity.cs

125 lines
4.6 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: RobinActivity.cs
//
// Note:
//
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.Singularity.Scheduling;
namespace Microsoft.Singularity.Scheduling.Robin
{
/// <summary>
/// The resource container class includes a recurring reservation
/// (k out of every n), a list of runnable threads, unfinished constraints
/// (i.e. non-guaranteed or non-feasible), as well as pointers to handle
/// its role in lists for the non-blocked activity list.
// It also has references for the last node to execute it,
/// a node assigned to it (which is a list via SameActivityNext), and a node
/// assigned to it under the new scheduling plan. It also has some bookkeeping.
/// </summary>
public class RobinActivity : ISchedulerActivity
{
private Activity enclosingActivity;
public RecurringReservation MyRecurringCpuReservation;
public RobinThread RunnableThreads;// list of runnable threads, if any
public OneShotReservation UnfinishedConstraints;
public RobinActivity Next; // Next and previous activities
public RobinActivity Previous;
public int ReferenceCount;
public int CountNodes;
public RobinActivity()
{
//Below is InitializeActivity();
ReferenceCount = 1;
RunnableThreads = null;
// MyRecurringCpuReservation = new RecurringReservation();
// MyRecurringCpuReservation.EnclosingCpuReservation = new CpuResourceReservation(MyRecurringCpuReservation);
bool iflag = Processor.DisableInterrupts();
RobinScheduler.EnqueueActivity(this); // add in last position in RoundRobin!
Processor.RestoreInterrupts(iflag);
}
public void ReleaseActivity()
{
bool iflag = Processor.DisableInterrupts();
RobinScheduler.DequeueActivity(this); // update RoundRobin queue, if required.
Processor.RestoreInterrupts(iflag);
Scheduler.LogDeleteActivity();
}
//public-normal API
//TODO: Call this from finalize?
public override void ReleaseReference()
{
// DI replaced by AtomicDec(&activity->ReferenceCount);
Debug.Assert(ReferenceCount > 0);
int newrefcnt = Interlocked.Decrement(ref ReferenceCount);
if (newrefcnt == CountNodes) {
if (CountNodes > 0) {
return;
}
bool iflag = Processor.DisableInterrupts();
RobinScheduler.DequeueActivity(this); // update RoundRobin queue, if required.
Processor.RestoreInterrupts(iflag);
}
Scheduler.LogDeleteActivity();
}
// find the runnable thread of an activity:
public RobinThread GetRunnableThread()
{
OneShotReservation reservation = UnfinishedConstraints;
Debug.Assert(reservation == null || reservation.AssociatedActivity == null); // avoid stack overflow : GetRunnableThread & GetRunnableThread
while (reservation != null) {
// search in the circular list
RobinThread thread = reservation.GetRunnableThread();
if (thread != null) {
return thread;
}
reservation = reservation.Next;
if (reservation == UnfinishedConstraints) {
break;
}
}
RobinThread runThread = RunnableThreads;
while (runThread != null && runThread.ActiveProcessor != null && runThread != RunnableThreads.Previous) {
runThread = runThread.Next;
}
if (runThread == null || runThread.ActiveProcessor != null) {
return null;
}
else {
return runThread;
}
}
#region ISchedulerActivity Members
public override Activity EnclosingActivity
{
get { return enclosingActivity; }
set { enclosingActivity = value; }
}
public CpuResourceReservation CpuResourceReservation
{
get { return MyRecurringCpuReservation.EnclosingCpuReservation; }
}
#endregion
}
}