//////////////////////////////////////////////////////////////////////////////// // // 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(); } } } }