From 50dfb4359619563012997bc3ddafb7667741066c Mon Sep 17 00:00:00 2001 From: Mamadou DIOP Date: Tue, 23 Feb 2016 22:00:35 +0100 Subject: Add new QoS implementation Code formatting --- tinySAK/winrt/ThreadEmulation.cxx | 482 ++++++++++++++++++-------------------- tinySAK/winrt/ThreadEmulation.h | 28 +-- 2 files changed, 244 insertions(+), 266 deletions(-) (limited to 'tinySAK/winrt') diff --git a/tinySAK/winrt/ThreadEmulation.cxx b/tinySAK/winrt/ThreadEmulation.cxx index f863dc9..91f2294 100755 --- a/tinySAK/winrt/ThreadEmulation.cxx +++ b/tinySAK/winrt/ThreadEmulation.cxx @@ -21,335 +21,313 @@ using namespace Windows::System::Threading; namespace ThreadEmulation { - // Stored data for CREATE_SUSPENDED and ResumeThread. - struct PendingThreadInfo - { - LPTHREAD_START_ROUTINE lpStartAddress; - LPVOID lpParameter; - HANDLE completionEvent; - int nPriority; - }; - - static map pendingThreads; - static mutex pendingThreadsLock; - - - // Thread local storage. - typedef vector ThreadLocalData; - - static __declspec(thread) ThreadLocalData* currentThreadData = nullptr; - static set allThreadData; - static DWORD nextTlsIndex = 0; - static vector freeTlsIndices; - static mutex tlsAllocationLock; - - - // Converts a Win32 thread priority to WinRT format. - static WorkItemPriority GetWorkItemPriority(int nPriority) - { - if (nPriority < 0) - return WorkItemPriority::Low; - else if (nPriority > 0) - return WorkItemPriority::High; - else - return WorkItemPriority::Normal; - } +// Stored data for CREATE_SUSPENDED and ResumeThread. +struct PendingThreadInfo { + LPTHREAD_START_ROUTINE lpStartAddress; + LPVOID lpParameter; + HANDLE completionEvent; + int nPriority; +}; +static map pendingThreads; +static mutex pendingThreadsLock; - // Helper shared between CreateThread and ResumeThread. - static void StartThread(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, HANDLE completionEvent, int nPriority) - { - auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) - { - // Run the user callback. - try - { - lpStartAddress(lpParameter); - } - catch (...) { } - // Clean up any TLS allocations made by this thread. - TlsShutdown(); +// Thread local storage. +typedef vector ThreadLocalData; - // Signal that the thread has completed. - SetEvent(completionEvent); - CloseHandle(completionEvent); +static __declspec(thread) ThreadLocalData* currentThreadData = nullptr; +static set allThreadData; +static DWORD nextTlsIndex = 0; +static vector freeTlsIndices; +static mutex tlsAllocationLock; - }, CallbackContext::Any); - ThreadPool::RunAsync(workItemHandler, GetWorkItemPriority(nPriority), WorkItemOptions::TimeSliced); +// Converts a Win32 thread priority to WinRT format. +static WorkItemPriority GetWorkItemPriority(int nPriority) +{ + if (nPriority < 0) { + return WorkItemPriority::Low; + } + else if (nPriority > 0) { + return WorkItemPriority::High; + } + else { + return WorkItemPriority::Normal; } +} - _Use_decl_annotations_ HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES unusedThreadAttributes, SIZE_T unusedStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD unusedThreadId) - { - // Validate parameters. - assert(unusedThreadAttributes == nullptr); - assert(unusedStackSize == 0); - assert((dwCreationFlags & ~CREATE_SUSPENDED) == 0); - assert(unusedThreadId == nullptr); +// Helper shared between CreateThread and ResumeThread. +static void StartThread(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, HANDLE completionEvent, int nPriority) +{ + auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) { + // Run the user callback. + try { + lpStartAddress(lpParameter); + } + catch (...) { } - // Create a handle that will be signalled when the thread has completed. - HANDLE threadHandle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + // Clean up any TLS allocations made by this thread. + TlsShutdown(); - if (!threadHandle) - return nullptr; + // Signal that the thread has completed. + SetEvent(completionEvent); + CloseHandle(completionEvent); - // Make a copy of the handle for internal use. This is necessary because - // the caller is responsible for closing the handle returned by CreateThread, - // and they may do that before or after the thread has finished running. - HANDLE completionEvent; - - if (!DuplicateHandle(GetCurrentProcess(), threadHandle, GetCurrentProcess(), &completionEvent, 0, false, DUPLICATE_SAME_ACCESS)) - { - CloseHandle(threadHandle); - return nullptr; - } + }, CallbackContext::Any); - try - { - if (dwCreationFlags & CREATE_SUSPENDED) - { - // Store info about a suspended thread. - PendingThreadInfo info; + ThreadPool::RunAsync(workItemHandler, GetWorkItemPriority(nPriority), WorkItemOptions::TimeSliced); +} - info.lpStartAddress = lpStartAddress; - info.lpParameter = lpParameter; - info.completionEvent = completionEvent; - info.nPriority = 0; - lock_guard lock(pendingThreadsLock); +_Use_decl_annotations_ HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES unusedThreadAttributes, SIZE_T unusedStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD unusedThreadId) +{ + // Validate parameters. + assert(unusedThreadAttributes == nullptr); + assert(unusedStackSize == 0); + assert((dwCreationFlags & ~CREATE_SUSPENDED) == 0); + assert(unusedThreadId == nullptr); - pendingThreads[threadHandle] = info; - } - else - { - // Start the thread immediately. - StartThread(lpStartAddress, lpParameter, completionEvent, 0); - } - - return threadHandle; - } - catch (...) - { - // Clean up if thread creation fails. - CloseHandle(threadHandle); - CloseHandle(completionEvent); + // Create a handle that will be signalled when the thread has completed. + HANDLE threadHandle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - return nullptr; - } + if (!threadHandle) { + return nullptr; } + // Make a copy of the handle for internal use. This is necessary because + // the caller is responsible for closing the handle returned by CreateThread, + // and they may do that before or after the thread has finished running. + HANDLE completionEvent; - _Use_decl_annotations_ DWORD WINAPI ResumeThread(HANDLE hThread) - { - lock_guard lock(pendingThreadsLock); + if (!DuplicateHandle(GetCurrentProcess(), threadHandle, GetCurrentProcess(), &completionEvent, 0, false, DUPLICATE_SAME_ACCESS)) { + CloseHandle(threadHandle); + return nullptr; + } - // Look up the requested thread. - auto threadInfo = pendingThreads.find(hThread); + try { + if (dwCreationFlags & CREATE_SUSPENDED) { + // Store info about a suspended thread. + PendingThreadInfo info; - if (threadInfo == pendingThreads.end()) - { - // Can only resume threads while they are in CREATE_SUSPENDED state. - assert(false); - return (DWORD)-1; - } + info.lpStartAddress = lpStartAddress; + info.lpParameter = lpParameter; + info.completionEvent = completionEvent; + info.nPriority = 0; - // Start the thread. - try - { - PendingThreadInfo& info = threadInfo->second; + lock_guard lock(pendingThreadsLock); - StartThread(info.lpStartAddress, info.lpParameter, info.completionEvent, info.nPriority); + pendingThreads[threadHandle] = info; } - catch (...) - { - return (DWORD)-1; + else { + // Start the thread immediately. + StartThread(lpStartAddress, lpParameter, completionEvent, 0); } - // Remove this thread from the pending list. - pendingThreads.erase(threadInfo); + return threadHandle; + } + catch (...) { + // Clean up if thread creation fails. + CloseHandle(threadHandle); + CloseHandle(completionEvent); - return 0; + return nullptr; } +} - _Use_decl_annotations_ BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority) - { - lock_guard lock(pendingThreadsLock); +_Use_decl_annotations_ DWORD WINAPI ResumeThread(HANDLE hThread) +{ + lock_guard lock(pendingThreadsLock); - // Look up the requested thread. - auto threadInfo = pendingThreads.find(hThread); + // Look up the requested thread. + auto threadInfo = pendingThreads.find(hThread); - if (threadInfo == pendingThreads.end()) - { - // Can only set priority on threads while they are in CREATE_SUSPENDED state. - return false; - } + if (threadInfo == pendingThreads.end()) { + // Can only resume threads while they are in CREATE_SUSPENDED state. + assert(false); + return (DWORD)-1; + } - // Store the new priority. - threadInfo->second.nPriority = nPriority; + // Start the thread. + try { + PendingThreadInfo& info = threadInfo->second; - return true; + StartThread(info.lpStartAddress, info.lpParameter, info.completionEvent, info.nPriority); + } + catch (...) { + return (DWORD)-1; } + // Remove this thread from the pending list. + pendingThreads.erase(threadInfo); - _Use_decl_annotations_ VOID WINAPI Sleep(DWORD dwMilliseconds) - { - static HANDLE singletonEvent = nullptr; + return 0; +} - HANDLE sleepEvent = singletonEvent; - // Demand create the event. - if (!sleepEvent) - { - sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - - if (!sleepEvent) - return; - - HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr); - - if (previousEvent) - { - // Back out if multiple threads try to demand create at the same time. - CloseHandle(sleepEvent); - sleepEvent = previousEvent; - } - } +_Use_decl_annotations_ BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority) +{ + lock_guard lock(pendingThreadsLock); + + // Look up the requested thread. + auto threadInfo = pendingThreads.find(hThread); - // Emulate sleep by waiting with timeout on an event that is never signalled. - WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); + if (threadInfo == pendingThreads.end()) { + // Can only set priority on threads while they are in CREATE_SUSPENDED state. + return false; } + // Store the new priority. + threadInfo->second.nPriority = nPriority; - DWORD WINAPI TlsAlloc() - { - lock_guard lock(tlsAllocationLock); - - // Can we reuse a previously freed TLS slot? - if (!freeTlsIndices.empty()) - { - DWORD result = freeTlsIndices.back(); - freeTlsIndices.pop_back(); - return result; - } + return true; +} - // Allocate a new TLS slot. - return nextTlsIndex++; - } +_Use_decl_annotations_ VOID WINAPI Sleep(DWORD dwMilliseconds) +{ + static HANDLE singletonEvent = nullptr; - _Use_decl_annotations_ BOOL WINAPI TlsFree(DWORD dwTlsIndex) - { - lock_guard lock(tlsAllocationLock); + HANDLE sleepEvent = singletonEvent; - assert(dwTlsIndex < nextTlsIndex); - assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), dwTlsIndex) == freeTlsIndices.end()); + // Demand create the event. + if (!sleepEvent) { + sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - // Store this slot for reuse by TlsAlloc. - try - { - freeTlsIndices.push_back(dwTlsIndex); - } - catch (...) - { - return false; + if (!sleepEvent) { + return; } - // Zero the value for all threads that might be using this now freed slot. - for each (auto threadData in allThreadData) - { - if (threadData->size() > dwTlsIndex) - { - threadData->at(dwTlsIndex) = nullptr; - } + HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr); + + if (previousEvent) { + // Back out if multiple threads try to demand create at the same time. + CloseHandle(sleepEvent); + sleepEvent = previousEvent; } + } + + // Emulate sleep by waiting with timeout on an event that is never signalled. + WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); +} + - return true; +DWORD WINAPI TlsAlloc() +{ + lock_guard lock(tlsAllocationLock); + + // Can we reuse a previously freed TLS slot? + if (!freeTlsIndices.empty()) { + DWORD result = freeTlsIndices.back(); + freeTlsIndices.pop_back(); + return result; } + // Allocate a new TLS slot. + return nextTlsIndex++; +} - _Use_decl_annotations_ LPVOID WINAPI TlsGetValue(DWORD dwTlsIndex) - { - ThreadLocalData* threadData = currentThreadData; - if (threadData && threadData->size() > dwTlsIndex) - { - // Return the value of an allocated TLS slot. - return threadData->at(dwTlsIndex); - } - else - { - // Default value for unallocated slots. - return nullptr; +_Use_decl_annotations_ BOOL WINAPI TlsFree(DWORD dwTlsIndex) +{ + lock_guard lock(tlsAllocationLock); + + assert(dwTlsIndex < nextTlsIndex); + assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), dwTlsIndex) == freeTlsIndices.end()); + + // Store this slot for reuse by TlsAlloc. + try { + freeTlsIndices.push_back(dwTlsIndex); + } + catch (...) { + return false; + } + + // Zero the value for all threads that might be using this now freed slot. + for each (auto threadData in allThreadData) { + if (threadData->size() > dwTlsIndex) { + threadData->at(dwTlsIndex) = nullptr; } } + return true; +} - _Use_decl_annotations_ BOOL WINAPI TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) - { - ThreadLocalData* threadData = currentThreadData; - if (!threadData) - { - // First time allocation of TLS data for this thread. - try - { - threadData = new ThreadLocalData(dwTlsIndex + 1, nullptr); - - lock_guard lock(tlsAllocationLock); +_Use_decl_annotations_ LPVOID WINAPI TlsGetValue(DWORD dwTlsIndex) +{ + ThreadLocalData* threadData = currentThreadData; + + if (threadData && threadData->size() > dwTlsIndex) { + // Return the value of an allocated TLS slot. + return threadData->at(dwTlsIndex); + } + else { + // Default value for unallocated slots. + return nullptr; + } +} - allThreadData.insert(threadData); - currentThreadData = threadData; - } - catch (...) - { - if (threadData) - delete threadData; +_Use_decl_annotations_ BOOL WINAPI TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) +{ + ThreadLocalData* threadData = currentThreadData; + + if (!threadData) { + // First time allocation of TLS data for this thread. + try { + threadData = new ThreadLocalData(dwTlsIndex + 1, nullptr); + + lock_guard lock(tlsAllocationLock); + + allThreadData.insert(threadData); - return false; + currentThreadData = threadData; + } + catch (...) { + if (threadData) { + delete threadData; } + + return false; } - else if (threadData->size() <= dwTlsIndex) - { - // This thread already has a TLS data block, but it must be expanded to fit the specified slot. - try - { - lock_guard lock(tlsAllocationLock); + } + else if (threadData->size() <= dwTlsIndex) { + // This thread already has a TLS data block, but it must be expanded to fit the specified slot. + try { + lock_guard lock(tlsAllocationLock); - threadData->resize(dwTlsIndex + 1, nullptr); - } - catch (...) - { - return false; - } + threadData->resize(dwTlsIndex + 1, nullptr); } + catch (...) { + return false; + } + } - // Store the new value for this slot. - threadData->at(dwTlsIndex) = lpTlsValue; + // Store the new value for this slot. + threadData->at(dwTlsIndex) = lpTlsValue; - return true; - } + return true; +} - // Called at thread exit to clean up TLS allocations. - void WINAPI TlsShutdown() - { - ThreadLocalData* threadData = currentThreadData; +// Called at thread exit to clean up TLS allocations. +void WINAPI TlsShutdown() +{ + ThreadLocalData* threadData = currentThreadData; - if (threadData) + if (threadData) { { - { - lock_guard lock(tlsAllocationLock); + lock_guard lock(tlsAllocationLock); - allThreadData.erase(threadData); - } + allThreadData.erase(threadData); + } - currentThreadData = nullptr; + currentThreadData = nullptr; - delete threadData; - } + delete threadData; } +} } \ No newline at end of file diff --git a/tinySAK/winrt/ThreadEmulation.h b/tinySAK/winrt/ThreadEmulation.h index 37deabc..b07bb13 100755 --- a/tinySAK/winrt/ThreadEmulation.h +++ b/tinySAK/winrt/ThreadEmulation.h @@ -34,20 +34,20 @@ namespace ThreadEmulation { - #ifndef CREATE_SUSPENDED - #define CREATE_SUSPENDED 0x00000004 - #endif +#ifndef CREATE_SUSPENDED +#define CREATE_SUSPENDED 0x00000004 +#endif - HANDLE WINAPI CreateThread(_In_opt_ LPSECURITY_ATTRIBUTES unusedThreadAttributes, _In_ SIZE_T unusedStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD unusedThreadId); - DWORD WINAPI ResumeThread(_In_ HANDLE hThread); - BOOL WINAPI SetThreadPriority(_In_ HANDLE hThread, _In_ int nPriority); - - VOID WINAPI Sleep(_In_ DWORD dwMilliseconds); +HANDLE WINAPI CreateThread(_In_opt_ LPSECURITY_ATTRIBUTES unusedThreadAttributes, _In_ SIZE_T unusedStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD unusedThreadId); +DWORD WINAPI ResumeThread(_In_ HANDLE hThread); +BOOL WINAPI SetThreadPriority(_In_ HANDLE hThread, _In_ int nPriority); - DWORD WINAPI TlsAlloc(); - BOOL WINAPI TlsFree(_In_ DWORD dwTlsIndex); - LPVOID WINAPI TlsGetValue(_In_ DWORD dwTlsIndex); - BOOL WINAPI TlsSetValue(_In_ DWORD dwTlsIndex, _In_opt_ LPVOID lpTlsValue); - - void WINAPI TlsShutdown(); +VOID WINAPI Sleep(_In_ DWORD dwMilliseconds); + +DWORD WINAPI TlsAlloc(); +BOOL WINAPI TlsFree(_In_ DWORD dwTlsIndex); +LPVOID WINAPI TlsGetValue(_In_ DWORD dwTlsIndex); +BOOL WINAPI TlsSetValue(_In_ DWORD dwTlsIndex, _In_opt_ LPVOID lpTlsValue); + +void WINAPI TlsShutdown(); } -- cgit v1.1