From 12e3e7f057bdb3d965a944d6c97fe7f222158eee Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Thu, 25 Dec 2014 19:42:00 +0000 Subject: files structure changed git-svn-id: http://svn.miranda-ng.org/main/trunk@11638 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_core/threads.cpp | 364 ----------------------------------------------- 1 file changed, 364 deletions(-) delete mode 100644 src/mir_core/threads.cpp (limited to 'src/mir_core/threads.cpp') diff --git a/src/mir_core/threads.cpp b/src/mir_core/threads.cpp deleted file mode 100644 index b1d6a23ebd..0000000000 --- a/src/mir_core/threads.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "commonheaders.h" - -#include - -///////////////////////////////////////////////////////////////////////////////////////// -// APC and mutex functions - -static void __stdcall DummyAPCFunc(ULONG_PTR) -{ - /* called in the context of thread that cleared it's APC queue */ - return; -} - -static int MirandaWaitForMutex(HANDLE hEvent) -{ - for (;;) { - // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result - DWORD rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); - if (rc == WAIT_OBJECT_0 + 1) { - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - if (IsDialogMessage(msg.hwnd, &msg)) continue; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - else if (rc == WAIT_OBJECT_0) { // got object - return 1; - } - else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED) - return 0; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// exception handling - -static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*) -{ - return EXCEPTION_EXECUTE_HANDLER; -} - -pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter; - -MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter() -{ - return pMirandaExceptFilter; -} - -MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter pMirandaExceptFilter) -{ - pfnExceptionFilter oldOne = pMirandaExceptFilter; - if (pMirandaExceptFilter != 0) - pMirandaExceptFilter = pMirandaExceptFilter; - return oldOne; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// thread support functions - -struct THREAD_WAIT_ENTRY -{ - DWORD dwThreadId; // valid if hThread isn't signalled - HANDLE hThread; - HINSTANCE hOwner; - void *pObject, *pEntryPoint; -}; - -static LIST threads(10, NumericKeySortT); - -struct FORK_ARG -{ - HANDLE hEvent; - union - { - pThreadFunc threadcode; - pThreadFuncEx threadcodeex; - }; - void *arg, *owner; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// forkthread - starts a new thread - -void __cdecl forkthread_r(void *arg) -{ - FORK_ARG *fa = (FORK_ARG*)arg; - pThreadFunc callercode = fa->threadcode; - void *cookie = fa->arg; - Thread_Push((HINSTANCE)callercode); - SetEvent(fa->hEvent); - - callercode(cookie); - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - Thread_Pop(); -} - -MIR_CORE_DLL(UINT_PTR) forkthread(void(__cdecl *threadcode)(void*), unsigned long stacksize, void *arg) -{ - FORK_ARG fa; - fa.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - fa.threadcode = threadcode; - fa.arg = arg; - UINT_PTR rc = _beginthread(forkthread_r, stacksize, &fa); - if ((UINT_PTR)-1L != rc) - WaitForSingleObject(fa.hEvent, INFINITE); - - CloseHandle(fa.hEvent); - return rc; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// forkthreadex - starts a new thread with the extended info and returns the thread id - -unsigned __stdcall forkthreadex_r(void * arg) -{ - struct FORK_ARG *fa = (struct FORK_ARG *)arg; - pThreadFuncEx threadcode = fa->threadcodeex; - pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex; - void *cookie = fa->arg; - void *owner = fa->owner; - unsigned long rc = 0; - - Thread_Push((HINSTANCE)threadcode, fa->owner); - SetEvent(fa->hEvent); - if (owner) - rc = threadcodeex(owner, cookie); - else - rc = threadcode(cookie); - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - Thread_Pop(); - return rc; -} - -MIR_CORE_DLL(UINT_PTR) forkthreadex( - void *sec, - unsigned stacksize, - unsigned(__stdcall *threadcode)(void*), - void *owner, - void *arg, - unsigned *thraddr) -{ - struct FORK_ARG fa = { 0 }; - fa.threadcodeex = threadcode; - fa.arg = arg; - fa.owner = owner; - fa.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - UINT_PTR rc = _beginthreadex(sec, stacksize, forkthreadex_r, (void *)&fa, 0, thraddr); - if (rc) - WaitForSingleObject(fa.hEvent, INFINITE); - - CloseHandle(fa.hEvent); - return rc; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(void) KillObjectThreads(void* owner) -{ - if (owner == NULL) - return; - - WaitForSingleObject(hStackMutex, INFINITE); - - HANDLE *threadPool = (HANDLE*)alloca(threads.getCount()*sizeof(HANDLE)); - int threadCount = 0; - - for (int j = threads.getCount(); j--;) { - THREAD_WAIT_ENTRY *p = threads[j]; - if (p->pObject == owner) - threadPool[threadCount++] = p->hThread; - } - ReleaseMutex(hStackMutex); - - // is there anything to kill? - if (threadCount > 0) { - if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) == WAIT_TIMEOUT) { - // forcibly kill all remaining threads after 5 secs - WaitForSingleObject(hStackMutex, INFINITE); - for (int j = threads.getCount() - 1; j >= 0; j--) { - THREAD_WAIT_ENTRY* p = threads[j]; - if (p->pObject == owner) { - char szModuleName[MAX_PATH]; - GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName)); - Netlib_Logf(0, "Killing objec thread %s:%p", szModuleName, p->dwThreadId); - TerminateThread(p->hThread, 9999); - CloseHandle(p->hThread); - threads.remove(j); - mir_free(p); - } - } - ReleaseMutex(hStackMutex); - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD) -{ - if (MirandaWaitForMutex(hStackMutex)) { - for (int j = 0; j < threads.getCount(); j++) { - THREAD_WAIT_ENTRY *p = threads[j]; - char szModuleName[MAX_PATH]; - GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName)); - Netlib_Logf(0, "Killing thread %s:%p (%p)", szModuleName, p->dwThreadId, p->pEntryPoint); - TerminateThread(p->hThread, 9999); - CloseHandle(p->hThread); - mir_free(p); - } - - threads.destroy(); - - ReleaseMutex(hStackMutex); - SetEvent(hThreadQueueEmpty); - } -} - -MIR_CORE_DLL(void) Thread_Wait(void) -{ - // acquire the list and wake up any alertable threads - if (MirandaWaitForMutex(hStackMutex)) { - for (int j = 0; j < threads.getCount(); j++) - QueueUserAPC(DummyAPCFunc, threads[j]->hThread, 0); - ReleaseMutex(hStackMutex); - } - - // give all unclosed threads 5 seconds to close - SetTimer(NULL, 0, 5000, KillAllThreads); - - // wait til the thread list is empty - MirandaWaitForMutex(hThreadQueueEmpty); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG); -#define ThreadQuerySetWin32StartAddress 9 - -static void* GetCurrentThreadEntryPoint() -{ - pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueryInformationThread"); - if (NtQueryInformationThread == NULL) return 0; - - HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess(); - if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - DWORD_PTR dwStartAddress; - LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), NULL); - CloseHandle(hDupHandle); - - return (ntStatus != ERROR_SUCCESS) ? NULL : (void*)dwStartAddress; -} - -MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner) -{ - ResetEvent(hThreadQueueEmpty); // thread list is not empty - if (WaitForSingleObject(hStackMutex, INFINITE) == WAIT_OBJECT_0) { - THREAD_WAIT_ENTRY* p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY)); - - DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); - p->dwThreadId = GetCurrentThreadId(); - p->pObject = pOwner; - if (pluginListAddr.getIndex(hInst) != -1) - p->hOwner = hInst; - else - p->hOwner = GetInstByAddress((hInst != NULL) ? (PVOID)hInst : GetCurrentThreadEntryPoint()); - p->pEntryPoint = hInst; - - threads.insert(p); - - ReleaseMutex(hStackMutex); - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(INT_PTR) Thread_Pop() -{ - if (WaitForSingleObject(hStackMutex, INFINITE) == WAIT_OBJECT_0) { - DWORD dwThreadId = GetCurrentThreadId(); - for (int j = 0; j < threads.getCount(); j++) { - THREAD_WAIT_ENTRY *p = threads[j]; - if (p->dwThreadId == dwThreadId) { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - CloseHandle(p->hThread); - threads.remove(j); - mir_free(p); - - if (!threads.getCount()) { - threads.destroy(); - ReleaseMutex(hStackMutex); - SetEvent(hThreadQueueEmpty); // thread list is empty now - return 0; - } - - ReleaseMutex(hStackMutex); - return 0; - } - } - ReleaseMutex(hStackMutex); - } - return 1; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -const DWORD MS_VC_EXCEPTION=0x406D1388; - -#pragma pack(push,8) -typedef struct tagTHREADNAME_INFO -{ - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. -} THREADNAME_INFO; -#pragma pack(pop) - -MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName) -{ - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = szThreadName; - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; - - __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); - } - __except (EXCEPTION_EXECUTE_HANDLER) - {} -} -- cgit v1.2.3