121 lines
4.9 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|