using System; using System.Runtime.InteropServices; using Vanara.InteropServices; namespace Vanara.PInvoke { public static partial class Kernel32 { /// public const uint UMS_VERSION = 0x0100; /// Flags used by UMS_SYSTEM_THREAD_INFORMATION. [PInvokeData("winbase.h", MSDNShortId = "eecdc592-5046-47c3-a4c6-ecb10899db3c")] public enum ThreadUmsFlags : uint { /// /// /// A bitfield that specifies a UMS scheduler thread. If IsUmsSchedulerThread is set, IsUmsWorkerThread must be clear. /// /// IsUmsSchedulerThread = 0x1, /// /// /// A bitfield that specifies a UMS worker thread. If IsUmsWorkerThread is set, IsUmsSchedulerThread must be clear. /// /// IsUmsWorkerThread = 0x2, } /// /// Creates a user-mode scheduling (UMS) completion list. /// /// /// A PUMS_COMPLETION_LIST variable. On output, this parameter receives a pointer to an empty UMS completion list. /// /// /// If the function succeeds, it returns a nonzero value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Not enough memory is available to create the completion list. /// /// /// /// /// /// A completion list is associated with a UMS scheduler thread when the EnterUmsSchedulingMode function is called to create the /// scheduler thread. The system queues newly created UMS worker threads to the completion list. It also queues previously blocked /// UMS worker threads to the completion list when the threads are no longer blocked. /// /// /// When an application's UmsSchedulerProc entry point function is called, the application's scheduler should retrieve items from the /// completion list by calling DequeueUmsCompletionListItems. /// /// /// Each completion list has an associated completion list event which is signaled whenever the system queues items to an empty list. /// Use the GetUmsCompletionListEvent to obtain a handle to the event for a specified completion list. /// /// /// When a completion list is no longer needed, use the DeleteUmsCompletionList to release the list. The list must be empty before it /// can be released. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createumscompletionlist BOOL CreateUmsCompletionList( // PUMS_COMPLETION_LIST *UmsCompletionList ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "6e77b793-a82e-4e23-8c8b-7aff79d69346")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreateUmsCompletionList(out SafePUMS_COMPLETION_LIST UmsCompletionList); /// /// Creates a user-mode scheduling (UMS) thread context to represent a UMS worker thread. /// /// /// A PUMS_CONTEXT variable. On output, this parameter receives a pointer to a UMS thread context. /// /// /// If the function succeeds, it returns a nonzero value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Not enough memory is available to create the UMS thread context. /// /// /// /// /// /// A UMS thread context represents the state of a UMS worker thread. Thread contexts are used to specify UMS worker threads in /// function calls. /// /// /// A UMS worker thread is created by calling the CreateRemoteThreadEx function after using InitializeProcThreadAttributeList and /// UpdateProcThreadAttribute to prepare a list of UMS attributes for the thread. /// /// /// The underlying structures for a UMS thread context are managed by the system and should not be modified directly. To get and set /// information about a UMS worker thread, use the QueryUmsThreadInformation and SetUmsThreadInformation functions. /// /// After a UMS worker thread terminates, its thread context should be released by calling DeleteUmsThreadContext. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createumsthreadcontext BOOL CreateUmsThreadContext( // PUMS_CONTEXT *lpUmsThread ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "b27ce81a-8463-46af-8acf-2de091f625df")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreateUmsThreadContext(out SafePUMS_CONTEXT lpUmsThread); /// /// Deletes the specified user-mode scheduling (UMS) completion list. The list must be empty. /// /// /// A pointer to the UMS completion list to be deleted. The CreateUmsCompletionList function provides this pointer. /// /// /// If the function succeeds, it returns a nonzero value. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// If the completion list is shared, the caller is responsible for ensuring that no active UMS thread holds a reference to the list /// before deleting it. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deleteumscompletionlist BOOL DeleteUmsCompletionList( // PUMS_COMPLETION_LIST UmsCompletionList ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "98124359-ddd1-468c-9f99-74dd3f631fa1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteUmsCompletionList(PUMS_COMPLETION_LIST UmsCompletionList); /// /// Deletes the specified user-mode scheduling (UMS) thread context. The thread must be terminated. /// /// /// A pointer to the UMS thread context to be deleted. The CreateUmsThreadContext function provides this pointer. /// /// /// If the function succeeds, it returns a nonzero value. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// A UMS thread context cannot be deleted until the associated thread has terminated. /// /// When a UMS worker thread finishes running (for example, by returning from its thread entry point function), the system terminates /// the thread, sets the termination status in the thread's UMS thread context, and queues the UMS thread context to the associated /// completion list. /// /// Any attempt to execute the UMS thread will fail because the thread is already terminated. /// /// To check the termination status of a thread, the application's scheduler should call QueryUmsThreadInformation with the /// UmsIsThreadTerminated information class. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deleteumsthreadcontext BOOL DeleteUmsThreadContext( // PUMS_CONTEXT UmsThread ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "cdd118fc-f664-44ce-958d-857216ceb9a7")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteUmsThreadContext(PUMS_CONTEXT UmsThread); /// /// Retrieves user-mode scheduling (UMS) worker threads from the specified UMS completion list. /// /// /// A pointer to the completion list from which to retrieve worker threads. /// /// /// /// The time-out interval for the retrieval operation, in milliseconds. The function returns if the interval elapses, even if no /// worker threads are queued to the completion list. /// /// /// If the WaitTimeOut parameter is zero, the completion list is checked for available worker threads without waiting for worker /// threads to become available. If the WaitTimeOut parameter is INFINITE, the function's time-out interval never elapses. This is /// not recommended, however, because it causes the function to block until one or more worker threads become available. /// /// /// /// /// A pointer to a UMS_CONTEXT variable. On output, this parameter receives a pointer to the first UMS thread context in a list of /// UMS thread contexts. /// /// /// If no worker threads are available before the time-out specified by the WaitTimeOut parameter, this parameter is set to NULL. /// /// /// /// If the function succeeds, it returns a nonzero value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_TIMEOUT /// No threads became available before the specified time-out interval elapsed. /// /// /// /// /// /// The system queues a UMS worker thread to a completion list when the worker thread is created or when a previously blocked worker /// thread becomes unblocked. The DequeueUmsCompletionListItems function retrieves a pointer to a list of all thread contexts /// in the specified completion list. The GetNextUmsListItem function can be used to pop UMS thread contexts off the list into the /// scheduler's own ready thread queue. The scheduler is responsible for selecting threads to run based on priorities chosen by the application. /// /// /// Do not run UMS threads directly from the list provided by DequeueUmsCompletionListItems, or run a thread transferred from /// the list to the ready thread queue before the list is completely empty. This can cause unpredictable behavior in the application. /// /// /// If more than one caller attempts to retrieve threads from a shared completion list, only the first caller retrieves the threads. /// For subsequent callers, the DequeueUmsCompletionListItems function returns success but the UmsThreadList parameter is set /// to NULL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-dequeueumscompletionlistitems BOOL // DequeueUmsCompletionListItems( PUMS_COMPLETION_LIST UmsCompletionList, DWORD WaitTimeOut, PUMS_CONTEXT *UmsThreadList ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "91499eb9-9fc5-4135-95f6-1bced78f1e07")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DequeueUmsCompletionListItems(PUMS_COMPLETION_LIST UmsCompletionList, uint WaitTimeOut, out PUMS_CONTEXT UmsThreadList); /// /// Converts the calling thread into a user-mode scheduling (UMS) scheduler thread. /// /// /// /// A pointer to a UMS_SCHEDULER_STARTUP_INFO structure that specifies UMS attributes for the thread, including a completion list and /// a UmsSchedulerProc entry point function. /// /// /// /// If the function succeeds, it returns a nonzero value. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// An application's UMS scheduler creates one UMS scheduler thread for each processor that will be used to run UMS threads. The /// scheduler typically sets the affinity of the scheduler thread for a single processor, effectively reserving the processor for the /// use of that scheduler thread. For more information about thread affinity, see Multiple Processors. /// /// /// When a UMS scheduler thread is created, the system calls the UmsSchedulerProc entry point function specified with the /// EnterUmsSchedulingMode function call. The application's scheduler is responsible for finishing any application-specific /// initialization of the scheduler thread and selecting a UMS worker thread to run. /// /// /// The application's scheduler selects a UMS worker thread to run by calling ExecuteUmsThread with the worker thread's UMS thread /// context. The worker thread runs until it yields control by calling UmsThreadYield, blocks, or terminates. The scheduler thread is /// then available to run another worker thread. /// /// /// A scheduler thread should continue to run until all of its worker threads reach a natural stopping point: that is, all worker /// threads have yielded, blocked, or terminated. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-enterumsschedulingmode BOOL EnterUmsSchedulingMode( // PUMS_SCHEDULER_STARTUP_INFO SchedulerStartupInfo ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "792bd7fa-0ae9-4c38-a664-5fb3e3d0c52b")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnterUmsSchedulingMode(in UMS_SCHEDULER_STARTUP_INFO SchedulerStartupInfo); /// /// Runs the specified UMS worker thread. /// /// /// A pointer to the UMS thread context of the worker thread to run. /// /// /// If the function succeeds, it does not return a value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error codes /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_RETRY /// The specified UMS worker thread is temporarily locked by the system. The caller can retry the operation. /// /// /// /// /// /// The ExecuteUmsThread function loads the state of the specified UMS worker thread over the state of the calling UMS /// scheduler thread so that the worker thread can run. The worker thread runs until it yields by calling the UmsThreadYield /// function, blocks, or terminates. /// /// /// When a worker thread yields or blocks, the system calls the scheduler thread's UmsSchedulerProc entry point function. When a /// previously blocked worker thread becomes unblocked, the system queues the worker thread to the completion list specified with the /// UpdateProcThreadAttribute function when the worker thread was created. /// /// /// The ExecuteUmsThread function does not return unless an error occurs. If the function returns ERROR_RETRY, the error is /// transitory and the operation can be retried. /// /// /// If the function returns an error other than ERROR_RETRY, the application's scheduler should check whether the thread is suspended /// or terminated by calling QueryUmsThreadInformation with UmsThreadIsSuspended or UmsThreadIsTerminated, /// respectively. Other possible errors include calling the function on a thread that is not a UMS scheduler thread, passing an /// invalid UMS worker thread context, or specifying a worker thread that is already executing on another scheduler thread. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-executeumsthread BOOL ExecuteUmsThread( PUMS_CONTEXT // UmsThread ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "e4265351-e8e9-4878-bd42-93258b4cd1a0")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ExecuteUmsThread(PUMS_CONTEXT UmsThread); /// /// Returns the user-mode scheduling (UMS) thread context of the calling UMS thread. /// /// /// The function returns a pointer to the UMS thread context of the calling thread. /// If calling thread is not a UMS thread, the function returns NULL. To get extended error information, call GetLastError. /// /// /// The GetCurrentUmsThread function can be called for a UMS scheduler thread or UMS worker thread. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcurrentumsthread PUMS_CONTEXT GetCurrentUmsThread( ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "f2e20816-919a-443d-96d3-94e98afc28f2")] public static extern PUMS_CONTEXT GetCurrentUmsThread(); /// Returns the next user-mode scheduling (UMS) thread context in a list of thread contexts. /// /// A pointer to a UMS context in a list of thread contexts. This list is retrieved by the DequeueUmsCompletionListItems function. /// /// /// If the function succeeds, it returns a pointer to the next thread context in the list. /// /// If there is no thread context after the context specified by the UmsContext parameter, the function returns NULL. To get extended /// error information, call GetLastError. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getnextumslistitem PUMS_CONTEXT GetNextUmsListItem( // PUMS_CONTEXT UmsContext ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "fb2c8420-12f4-4bd7-ac00-b53bab760db0")] public static extern PUMS_CONTEXT GetNextUmsListItem(PUMS_CONTEXT UmsContext); /// /// Retrieves a handle to the event associated with the specified user-mode scheduling (UMS) completion list. /// /// /// A pointer to a UMS completion list. The CreateUmsCompletionList function provides this pointer. /// /// /// /// A pointer to a HANDLE variable. On output, the UmsCompletionEvent parameter is set to a handle to the event associated with the /// specified completion list. /// /// /// /// If the function succeeds, it returns a nonzero value. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The system signals a UMS completion list event when the system queues items to an empty completion list. A completion list event /// handle can be used with any wait function that takes a handle to an event. When the event is signaled, an application typically /// calls DequeueUmsCompletionListItems to retrieve the contents of the completion list. /// /// /// The event handle remains valid until its completion list is deleted. Do not use the event handle to wait on a completion list /// that has been deleted or is in the process of being deleted. /// /// When the handle is no longer needed, use the CloseHandle function to close the handle. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getumscompletionlistevent BOOL GetUmsCompletionListEvent( // PUMS_COMPLETION_LIST UmsCompletionList, PHANDLE UmsCompletionEvent ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "393f6e0a-fbea-4aa0-9c18-f96da18e61e9")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetUmsCompletionListEvent(PUMS_COMPLETION_LIST UmsCompletionList, out SafeEventHandle UmsCompletionEvent); /// /// Queries whether the specified thread is a UMS scheduler thread, a UMS worker thread, or a non-UMS thread. /// /// /// /// A handle to a thread. The thread handle must have the THREAD_QUERY_INFORMATION access right. For more information, see Thread /// Security and Access Rights. /// /// /// /// A pointer to an initialized UMS_SYSTEM_THREAD_INFORMATION structure that specifies the kind of thread for the query. /// /// /// /// Returns TRUE if the specified thread matches the kind of thread specified by the SystemThreadInfo parameter. Otherwise, the /// function returns FALSE. /// /// /// /// /// The GetUmsSystemThreadInformation function is intended for use in debuggers, troubleshooting tools, and profiling /// applications. For example, thread-isolated tracing or single-stepping through instructions might involve suspending all other /// threads in the process. However, if the thread to be traced is a UMS worker thread, suspending UMS scheduler threads might cause /// a deadlock because a UMS worker thread requires the intervention of a UMS scheduler thread in order to run. A debugger can call /// GetUmsSystemThreadInformation for each thread that it might suspend to determine the kind of thread, and then suspend it /// or not as needed for the code being debugged. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getumssystemthreadinformation BOOL // GetUmsSystemThreadInformation( HANDLE ThreadHandle, PUMS_SYSTEM_THREAD_INFORMATION SystemThreadInfo ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "7c8347b6-6546-4ea9-9b2a-11794782f482")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetUmsSystemThreadInformation(HTHREAD ThreadHandle, ref UMS_SYSTEM_THREAD_INFORMATION SystemThreadInfo); /// Retrieves information about the specified user-mode scheduling (UMS) worker thread. /// A pointer to a UMS thread context. /// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to retrieve. /// /// /// A pointer to a buffer to receive the specified information. The required size of this buffer depends on the specified information class. /// /// If the information class is UmsThreadContext or UmsThreadTeb, the buffer must be . /// If the information class is UmsThreadIsSuspended or UmsThreadIsTerminated, the buffer must be . /// /// The size of the UmsThreadInformation buffer, in bytes. /// /// A pointer to a ULONG variable. On output, this parameter receives the number of bytes written to the UmsThreadInformation buffer. /// /// /// If the function succeeds, it returns a nonzero value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_INFO_LENGTH_MISMATCH /// The buffer is too small for the requested information. /// /// /// ERROR_INVALID_INFO_CLASS /// The specified information class is not supported. /// /// /// /// /// /// The QueryUmsThreadInformation function retrieves information about the specified UMS worker thread such as its /// application-defined context, its thread execution block (TEB), and whether the thread is suspended or terminated. /// /// /// The underlying structures for UMS worker threads are managed by the system. Information that is not exposed through /// QueryUmsThreadInformation should be considered reserved. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-queryumsthreadinformation BOOL QueryUmsThreadInformation( // PUMS_CONTEXT UmsThread, UMS_THREAD_INFO_CLASS UmsThreadInfoClass, PVOID UmsThreadInformation, ULONG UmsThreadInformationLength, // PULONG ReturnLength ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "5f694edf-ba5e-45a2-a938-5013edddcae2")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QueryUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass, IntPtr UmsThreadInformation, uint UmsThreadInformationLength, out uint ReturnLength); /// Retrieves information about the specified user-mode scheduling (UMS) worker thread. /// The return type being requested. /// A pointer to a UMS thread context. /// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to retrieve. /// The specified information of type . /// /// /// The QueryUmsThreadInformation function retrieves information about the specified UMS worker thread such as its /// application-defined context, its thread execution block (TEB), and whether the thread is suspended or terminated. /// /// /// The underlying structures for UMS worker threads are managed by the system. Information that is not exposed through /// QueryUmsThreadInformation should be considered reserved. /// /// public static T QueryUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass) where T : struct { if (!CorrespondingTypeAttribute.CanGet(UmsThreadInfoClass, typeof(T))) throw new ArgumentException($"Cannot use {UmsThreadInfoClass} to retrieve a value of {typeof(T).Name}."); if (!QueryUmsThreadInformation(UmsThread, UmsThreadInfoClass, IntPtr.Zero, 0, out var sz) && sz == 0) Win32Error.ThrowLastError(); using (var mem = new SafeHGlobalHandle(sz)) { if (!QueryUmsThreadInformation(UmsThread, UmsThreadInfoClass, mem, mem.Size, out sz)) Win32Error.ThrowLastError(); return typeof(T) == typeof(bool) ? (T)(object)(mem.ToStructure() != 0) : mem.ToStructure(); } } /// Sets application-specific context information for the specified user-mode scheduling (UMS) worker thread. /// A pointer to a UMS thread context. /// /// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to set. This parameter must be UmsThreadUserContext. /// /// A pointer to a buffer that contains the information to set. /// The size of the UmsThreadInformation buffer, in bytes. /// /// If the function succeeds, it returns a nonzero value. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values /// include the following. /// /// /// /// Return code /// Description /// /// /// ERROR_INFO_LENGTH_MISMATCH /// The buffer size does not match the required size for the specified information class. /// /// /// ERROR_INVALID_INFO_CLASS /// The UmsThreadInfoClass parameter specifies an information class that is not supported. /// /// /// /// /// /// The SetUmsThreadInformation function can be used to set an application-defined context for the specified UMS worker /// thread. The context information can consist of anything the application might find useful to track, such as per-scheduler or /// per-worker thread state. The underlying structures for UMS worker threads are managed by the system and should not be modified directly. /// /// /// The QueryUmsThreadInformation function can be used to retrieve other exposed information about the specified thread, such as its /// thread execution block (TEB) and whether the thread is suspended or terminated. Information that is not exposed through /// QueryUmsThreadInformation should be considered reserved. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setumsthreadinformation BOOL SetUmsThreadInformation( // PUMS_CONTEXT UmsThread, UMS_THREAD_INFO_CLASS UmsThreadInfoClass, PVOID UmsThreadInformation, ULONG UmsThreadInformationLength ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "19f190fd-1f78-4bb6-93eb-73a5c522b44d")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass, IntPtr UmsThreadInformation, uint UmsThreadInformationLength); /// /// Yields control to the user-mode scheduling (UMS) scheduler thread on which the calling UMS worker thread is running. /// /// /// A parameter to pass to the scheduler thread's UmsSchedulerProc function. /// /// /// If the function succeeds, it returns a nonzero value. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// A UMS worker thread calls the UmsThreadYield function to cooperatively yield control to the UMS scheduler thread on which /// the worker thread is running. If a UMS worker thread never calls UmsThreadYield, the worker thread runs until it either /// blocks or is terminated. /// /// /// When control switches to the UMS scheduler thread, the system calls the associated scheduler entry point function with the reason /// UmsSchedulerThreadYield and the ScheduleParam parameter specified by the worker thread in the UmsThreadYield call. /// /// The application's scheduler is responsible for rescheduling the worker thread. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-umsthreadyield BOOL UmsThreadYield( PVOID SchedulerParam ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winbase.h", MSDNShortId = "d7c94ed5-9536-4c39-8658-27e4237cc9ba")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UmsThreadYield(IntPtr SchedulerParam); /// Provides a handle to a completion list. [StructLayout(LayoutKind.Sequential)] public struct PUMS_COMPLETION_LIST : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public PUMS_COMPLETION_LIST(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static PUMS_COMPLETION_LIST NULL => new PUMS_COMPLETION_LIST(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(PUMS_COMPLETION_LIST h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator PUMS_COMPLETION_LIST(IntPtr h) => new PUMS_COMPLETION_LIST(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(PUMS_COMPLETION_LIST h1, PUMS_COMPLETION_LIST h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(PUMS_COMPLETION_LIST h1, PUMS_COMPLETION_LIST h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is PUMS_COMPLETION_LIST h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a handle to a UMS context. [StructLayout(LayoutKind.Sequential)] public struct PUMS_CONTEXT : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public PUMS_CONTEXT(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static PUMS_CONTEXT NULL => new PUMS_CONTEXT(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Gets a value indicating whether this instance is suspended. /// true if this instance is suspended; otherwise, false. public bool IsSuspended => QueryUmsThreadInformation(this, RTL_UMS_THREAD_INFO_CLASS.UmsThreadIsSuspended); /// Gets a value indicating whether this instance is terminated. /// true if this instance is terminated; otherwise, false. public bool IsTerminated => QueryUmsThreadInformation(this, RTL_UMS_THREAD_INFO_CLASS.UmsThreadIsTerminated); /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(PUMS_CONTEXT h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator PUMS_CONTEXT(IntPtr h) => new PUMS_CONTEXT(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(PUMS_CONTEXT h1, PUMS_CONTEXT h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(PUMS_CONTEXT h1, PUMS_CONTEXT h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is PUMS_CONTEXT h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// /// Specifies attributes for a user-mode scheduling (UMS) scheduler thread. The EnterUmsSchedulingMode function uses this structure. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_ums_scheduler_startup_info typedef struct // _UMS_SCHEDULER_STARTUP_INFO { ULONG UmsVersion; PUMS_COMPLETION_LIST CompletionList; PUMS_SCHEDULER_ENTRY_POINT SchedulerProc; // PVOID SchedulerParam; } UMS_SCHEDULER_STARTUP_INFO, *PUMS_SCHEDULER_STARTUP_INFO; [PInvokeData("winbase.h", MSDNShortId = "e3f7b1b7-d2b8-432d-bce7-3633292e855b")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct UMS_SCHEDULER_STARTUP_INFO { /// The UMS version for which the application was built. This parameter must be UMS_VERSION (0x0100). public uint UmsVersion; /// A pointer to a UMS completion list to associate with the calling thread. public PUMS_COMPLETION_LIST CompletionList; /// /// A pointer to an application-defined UmsSchedulerProc entry point function. The system calls this function when the calling /// thread has been converted to UMS and is ready to run UMS worker threads. Subsequently, it calls this function when a UMS /// worker thread running on the calling thread yields or blocks. /// public RtlUmsSchedulerEntryPoint SchedulerProc; /// An application-defined parameter to pass to the specified UmsSchedulerProc function. public IntPtr SchedulerParam; /// Initializes a new instance of the struct. /// A pointer to an application-defined UmsSchedulerProc entry point function. /// An application-defined parameter to pass to the specified UmsSchedulerProc function. /// A pointer to a UMS completion list to associate with the calling thread. public UMS_SCHEDULER_STARTUP_INFO(RtlUmsSchedulerEntryPoint schedulerProc, [Optional] IntPtr param, [Optional] PUMS_COMPLETION_LIST completionList) { UmsVersion = UMS_VERSION; CompletionList = completionList; SchedulerProc = schedulerProc; SchedulerParam = param; } } /// /// Specifies a UMS scheduler thread, UMS worker thread, or non-UMS thread. The GetUmsSystemThreadInformation function uses this structure. /// /// /// If both IsUmsSchedulerThread and IsUmsWorkerThread are clear, the structure specifies a non-UMS thread. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_ums_system_thread_information typedef struct // _UMS_SYSTEM_THREAD_INFORMATION { ULONG UmsVersion; union { struct { ULONG IsUmsSchedulerThread : 1; ULONG IsUmsWorkerThread : 1; } // DUMMYSTRUCTNAME; ULONG ThreadUmsFlags; } DUMMYUNIONNAME; } UMS_SYSTEM_THREAD_INFORMATION, *PUMS_SYSTEM_THREAD_INFORMATION; [PInvokeData("winbase.h", MSDNShortId = "eecdc592-5046-47c3-a4c6-ecb10899db3c")] [StructLayout(LayoutKind.Sequential)] public struct UMS_SYSTEM_THREAD_INFORMATION { /// /// The UMS version. This member must be UMS_VERSION. /// public uint UmsVersion; /// A bitfield that specifies a UMS thread type. public ThreadUmsFlags ThreadUmsFlags; /// Gets a default instance of this structure with the fields pre-set to default values. public static readonly UMS_SYSTEM_THREAD_INFORMATION Default = new UMS_SYSTEM_THREAD_INFORMATION { UmsVersion = UMS_VERSION }; } /// /// Provides a to a UMS completion list that releases a created UmsCompletionList instance at disposal using DeleteUmsCompletionList. /// public class SafePUMS_COMPLETION_LIST : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafePUMS_COMPLETION_LIST(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafePUMS_COMPLETION_LIST() : base() { } /// Converts to PUMS_COMPLETION_LIST. /// Safe list. public static implicit operator PUMS_COMPLETION_LIST(SafePUMS_COMPLETION_LIST l) => l.handle; /// protected override bool InternalReleaseHandle() => DeleteUmsCompletionList(handle); } /// /// Provides a to a UMS thread context that releases a created UmsThreadContext instance at disposal using DeleteUmsThreadContext. /// public class SafePUMS_CONTEXT : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafePUMS_CONTEXT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafePUMS_CONTEXT() : base() { } /// Converts to PUMS_CONTEXT. /// Safe context. public static implicit operator PUMS_CONTEXT(SafePUMS_CONTEXT c) => c.handle; /// protected override bool InternalReleaseHandle() => DeleteUmsThreadContext(handle); } } }