singrdk/base/Kernel/System/Threading/ThreadLocalServiceRequest.cs

121 lines
4.9 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: ThreadLocalServiceRequest.cs
//
// Note:
//
using Microsoft.Singularity;
namespace System.Threading
{
internal enum ThreadLocalServiceRequestTag
{
SuspendProcess,
SuspendProcessRecursive,
ResumeProcess,
ResumeProcessRecursive,
StopProcess,
ThreadStopped,
}
// Some service request objects should not be allocated on demand, because
// they are needed in low-memory situations. To handle these situations, each
// thread contains a preallocated, reusable ThreadLocalServiceRequest
// object whose tag describes the precise purpose of each request.
// This object should only be used by its own thread. The thread
// will block until the request is finished. After one request finishes,
// the thread may reuse its ThreadLocalServiceRequest for another
// request.
public class ThreadLocalServiceRequest : ServiceRequest
{
ThreadLocalServiceRequestTag tag;
Process targetProcess; // only relevant to SuspendProcess, SuspendProcessRecursive, ResumeProcess, ResumeProcessRecursive, StopProcess
Thread targetThread; // only relevant to ThreadStopped
int exitCode; // only relevant to StopProcess
AutoResetEvent requestFinished = new AutoResetEvent(false);
bool processStarted; // only relevant to SuspendProcess, ResumeProcess
[CLSCompliant(false)]
public static bool SuspendProcess(Process process, bool recursive)
{
ThreadLocalServiceRequest req = Thread.CurrentThread.localServiceRequest;
req.tag = (recursive)?
(ThreadLocalServiceRequestTag.SuspendProcessRecursive):
(ThreadLocalServiceRequestTag.SuspendProcess);
req.targetProcess = process;
ServiceThread.Request(req);
req.requestFinished.WaitOne();
return req.processStarted;
}
[CLSCompliant(false)]
public static bool ResumeProcess(Process process, bool recursive)
{
ThreadLocalServiceRequest req = Thread.CurrentThread.localServiceRequest;
req.tag = (recursive)?
(ThreadLocalServiceRequestTag.ResumeProcessRecursive):
(ThreadLocalServiceRequestTag.ResumeProcess);
req.targetProcess = process;
ServiceThread.Request(req);
req.requestFinished.WaitOne();
return req.processStarted;
}
[CLSCompliant(false)]
public static void StopProcess(Process process, int exitCode)
{
ThreadLocalServiceRequest req = Thread.CurrentThread.localServiceRequest;
req.tag = ThreadLocalServiceRequestTag.StopProcess;
req.targetProcess = process;
req.exitCode = exitCode;
ServiceThread.Request(req);
req.requestFinished.WaitOne();
process.Join();
}
public static void CurrentThreadStopped()
{
ThreadLocalServiceRequest req = Thread.CurrentThread.localServiceRequest;
req.tag = ThreadLocalServiceRequestTag.ThreadStopped;
req.targetThread = Thread.CurrentThread;
ServiceThread.Request(req);
// Do not wait for requestFinished; let the current thread die instead.
// (This is the last request this thread ever makes.)
}
protected override internal void Service()
{
try {
switch (tag) {
case ThreadLocalServiceRequestTag.SuspendProcess:
processStarted = targetProcess.ServiceSuspend(false);
break;
case ThreadLocalServiceRequestTag.SuspendProcessRecursive:
processStarted = targetProcess.ServiceSuspend(true);
break;
case ThreadLocalServiceRequestTag.ResumeProcess:
processStarted = targetProcess.ServiceResume(false);
break;
case ThreadLocalServiceRequestTag.ResumeProcessRecursive:
processStarted = targetProcess.ServiceResume(true);
break;
case ThreadLocalServiceRequestTag.StopProcess:
targetProcess.ServiceStop(exitCode);
break;
case ThreadLocalServiceRequestTag.ThreadStopped:
targetThread.ServiceStopped();
break;
}
}
finally {
requestFinished.Set();
}
}
}
}