| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- /**
- * WinPR: Windows Portable Runtime
- * Process Thread Functions
- *
- * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- * Copyright 2015 Hewlett-Packard Development Company, L.P.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <assert.h>
- #ifndef _WIN32
- #include <sched.h>
- #endif
- #include <winpr/handle.h>
- #include <winpr/thread.h>
- /**
- * api-ms-win-core-processthreads-l1-1-1.dll
- *
- * CreateRemoteThread
- * CreateRemoteThreadEx
- * CreateThread
- * DeleteProcThreadAttributeList
- * ExitThread
- * FlushInstructionCache
- * FlushProcessWriteBuffers
- * GetCurrentThread
- * GetCurrentThreadId
- * GetCurrentThreadStackLimits
- * GetExitCodeThread
- * GetPriorityClass
- * GetStartupInfoW
- * GetThreadContext
- * GetThreadId
- * GetThreadIdealProcessorEx
- * GetThreadPriority
- * GetThreadPriorityBoost
- * GetThreadTimes
- * InitializeProcThreadAttributeList
- * OpenThread
- * OpenThreadToken
- * QueryProcessAffinityUpdateMode
- * QueueUserAPC
- * ResumeThread
- * SetPriorityClass
- * SetThreadContext
- * SetThreadPriority
- * SetThreadPriorityBoost
- * SetThreadStackGuarantee
- * SetThreadToken
- * SuspendThread
- * SwitchToThread
- * TerminateThread
- * UpdateProcThreadAttribute
- */
- #ifndef _WIN32
- #include <winpr/crt.h>
- #include <winpr/platform.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_SYS_EVENTFD_H
- #include <sys/eventfd.h>
- #endif
- #include <winpr/debug.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <winpr/collections.h>
- #include "thread.h"
- #include "../handle/handle.h"
- #include "../log.h"
- #define TAG WINPR_TAG("thread")
- static wListDictionary* thread_list = NULL;
- static BOOL ThreadCloseHandle(HANDLE handle);
- static void cleanup_handle(void* obj);
- static BOOL ThreadIsHandled(HANDLE handle)
- {
- WINPR_THREAD* pThread = (WINPR_THREAD*)handle;
- if (!pThread || (pThread->Type != HANDLE_TYPE_THREAD))
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- return TRUE;
- }
- static int ThreadGetFd(HANDLE handle)
- {
- WINPR_THREAD* pThread = (WINPR_THREAD*)handle;
- if (!ThreadIsHandled(handle))
- return -1;
- return pThread->pipe_fd[0];
- }
- static DWORD ThreadCleanupHandle(HANDLE handle)
- {
- WINPR_THREAD* thread = (WINPR_THREAD*)handle;
- if (!ThreadIsHandled(handle))
- return WAIT_FAILED;
- if (pthread_mutex_lock(&thread->mutex))
- return WAIT_FAILED;
- if (!thread->joined)
- {
- int status;
- status = pthread_join(thread->thread, NULL);
- if (status != 0)
- {
- WLog_ERR(TAG, "pthread_join failure: [%d] %s", status, strerror(status));
- pthread_mutex_unlock(&thread->mutex);
- return WAIT_FAILED;
- }
- else
- thread->joined = TRUE;
- }
- if (pthread_mutex_unlock(&thread->mutex))
- return WAIT_FAILED;
- return WAIT_OBJECT_0;
- }
- static HANDLE_OPS ops = { ThreadIsHandled,
- ThreadCloseHandle,
- ThreadGetFd,
- ThreadCleanupHandle,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL };
- static void dump_thread(WINPR_THREAD* thread)
- {
- #if defined(WITH_DEBUG_THREADS)
- void* stack = winpr_backtrace(20);
- char** msg;
- size_t used, i;
- WLog_DBG(TAG, "Called from:");
- msg = winpr_backtrace_symbols(stack, &used);
- for (i = 0; i < used; i++)
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- free(msg);
- winpr_backtrace_free(stack);
- WLog_DBG(TAG, "Thread handle created still not closed!");
- msg = winpr_backtrace_symbols(thread->create_stack, &used);
- for (i = 0; i < used; i++)
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- free(msg);
- if (thread->started)
- {
- WLog_DBG(TAG, "Thread still running!");
- }
- else if (!thread->exit_stack)
- {
- WLog_DBG(TAG, "Thread suspended.");
- }
- else
- {
- WLog_DBG(TAG, "Thread exited at:");
- msg = winpr_backtrace_symbols(thread->exit_stack, &used);
- for (i = 0; i < used; i++)
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- free(msg);
- }
- #endif
- }
- /**
- * TODO: implement thread suspend/resume using pthreads
- * http://stackoverflow.com/questions/3140867/suspend-pthreads-without-using-condition
- */
- static BOOL set_event(WINPR_THREAD* thread)
- {
- int length;
- BOOL status = FALSE;
- #ifdef HAVE_SYS_EVENTFD_H
- eventfd_t val = 1;
- do
- {
- length = eventfd_write(thread->pipe_fd[0], val);
- } while ((length < 0) && (errno == EINTR));
- status = (length == 0) ? TRUE : FALSE;
- #else
- if (WaitForSingleObject(thread, 0) != WAIT_OBJECT_0)
- {
- length = write(thread->pipe_fd[1], "-", 1);
- if (length == 1)
- status = TRUE;
- }
- else
- {
- status = TRUE;
- }
- #endif
- return status;
- }
- static BOOL reset_event(WINPR_THREAD* thread)
- {
- int length;
- BOOL status = FALSE;
- #ifdef HAVE_SYS_EVENTFD_H
- eventfd_t value;
- do
- {
- length = eventfd_read(thread->pipe_fd[0], &value);
- } while ((length < 0) && (errno == EINTR));
- if ((length > 0) && (!status))
- status = TRUE;
- #else
- length = read(thread->pipe_fd[0], &length, 1);
- if ((length == 1) && (!status))
- status = TRUE;
- #endif
- return status;
- }
- static BOOL thread_compare(const void* a, const void* b)
- {
- const pthread_t* p1 = a;
- const pthread_t* p2 = b;
- BOOL rc = pthread_equal(*p1, *p2);
- return rc;
- }
- /* Thread launcher function responsible for registering
- * cleanup handlers and calling pthread_exit, if not done
- * in thread function. */
- static void* thread_launcher(void* arg)
- {
- DWORD rc = 0;
- WINPR_THREAD* thread = (WINPR_THREAD*)arg;
- LPTHREAD_START_ROUTINE fkt;
- if (!thread)
- {
- WLog_ERR(TAG, "Called with invalid argument %p", arg);
- goto exit;
- }
- if (!(fkt = thread->lpStartAddress))
- {
- WLog_ERR(TAG, "Thread function argument is %p", (void*)fkt);
- goto exit;
- }
- if (pthread_mutex_lock(&thread->threadIsReadyMutex))
- goto exit;
- if (!ListDictionary_Contains(thread_list, &thread->thread))
- {
- if (pthread_cond_wait(&thread->threadIsReady, &thread->threadIsReadyMutex) != 0)
- {
- WLog_ERR(TAG, "The thread could not be made ready");
- pthread_mutex_unlock(&thread->threadIsReadyMutex);
- goto exit;
- }
- }
- if (pthread_mutex_unlock(&thread->threadIsReadyMutex))
- goto exit;
- assert(ListDictionary_Contains(thread_list, &thread->thread));
- rc = fkt(thread->lpParameter);
- exit:
- if (thread)
- {
- if (!thread->exited)
- thread->dwExitCode = rc;
- set_event(thread);
- if (thread->detached || !thread->started)
- cleanup_handle(thread);
- }
- return NULL;
- }
- static BOOL winpr_StartThread(WINPR_THREAD* thread)
- {
- int inheritsched;
- struct sched_param param;
- int policy;
- int ret;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- /*start need root privilege or create thread would be failed.*/
- //PTHREAD_INHERIT_SCHED
- //ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
- //if (ret != 0) {
- // WLog_ERR(TAG, "pthread_attr_setinheritsched failed: %s", strerror(ret));
- // goto error;
- //}
- //param.sched_priority = 12;
- //policy = SCHED_FIFO;
- //ret = pthread_attr_setschedpolicy(&attr, policy);
- //if (ret != 0) {
- // WLog_ERR(TAG, "pthread_attr_setschedpolicy failed: %s", strerror(ret));
- // goto error;
- //}
- //ret = pthread_attr_setschedparam(&attr, ¶m);
- //if (ret != 0) {
- // WLog_ERR(TAG, "pthread_attr_setschedparam failed: %s", strerror(ret));
- // goto error;
- //}
- /*end*/
- if (thread->dwStackSize > 0)
- pthread_attr_setstacksize(&attr, (size_t)thread->dwStackSize);
- thread->started = TRUE;
- reset_event(thread);
- if (ret = pthread_create(&thread->thread, &attr, thread_launcher, thread))
- {
- WLog_ERR(TAG, "pthread_create failed: %s", strerror(ret));
- goto error;
- }
- if (pthread_mutex_lock(&thread->threadIsReadyMutex))
- goto error;
- if (!ListDictionary_Add(thread_list, &thread->thread, thread))
- {
- WLog_ERR(TAG, "failed to add the thread to the thread list");
- pthread_mutex_unlock(&thread->threadIsReadyMutex);
- goto error;
- }
- if (pthread_cond_signal(&thread->threadIsReady) != 0)
- {
- WLog_ERR(TAG, "failed to signal the thread was ready");
- pthread_mutex_unlock(&thread->threadIsReadyMutex);
- goto error;
- }
- if (pthread_mutex_unlock(&thread->threadIsReadyMutex))
- goto error;
- pthread_attr_destroy(&attr);
- dump_thread(thread);
- return TRUE;
- error:
- pthread_attr_destroy(&attr);
- return FALSE;
- }
- //HANDLE <-> WINPR_THREAD*
- //ThreadID <-> pthread_t or pthread_t*
- //Compare pthread_equal(*p1, *p2)
- HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
- DWORD dwCreationFlags, LPDWORD lpThreadId)
- {
- HANDLE handle;
- WINPR_THREAD* thread;
- thread = (WINPR_THREAD*)calloc(1, sizeof(WINPR_THREAD));
- if (!thread)
- return NULL;
- thread->dwStackSize = dwStackSize;
- thread->lpParameter = lpParameter;
- thread->lpStartAddress = lpStartAddress;
- thread->lpThreadAttributes = lpThreadAttributes;
- thread->ops = &ops;
- #if defined(WITH_DEBUG_THREADS)
- thread->create_stack = winpr_backtrace(20);
- dump_thread(thread);
- #endif
- thread->pipe_fd[0] = -1;
- thread->pipe_fd[1] = -1;
- #ifdef HAVE_SYS_EVENTFD_H
- thread->pipe_fd[0] = eventfd(0, EFD_NONBLOCK);
- if (thread->pipe_fd[0] < 0)
- {
- WLog_ERR(TAG, "failed to create thread pipe fd 0");
- goto error_pipefd0;
- }
- #else
- if (pipe(thread->pipe_fd) < 0)
- {
- WLog_ERR(TAG, "failed to create thread pipe");
- goto error_pipefd0;
- }
- {
- int flags = fcntl(thread->pipe_fd[0], F_GETFL);
- fcntl(thread->pipe_fd[0], F_SETFL, flags | O_NONBLOCK);
- }
- #endif
- if (pthread_mutex_init(&thread->mutex, 0) != 0)
- {
- WLog_ERR(TAG, "failed to initialize thread mutex");
- goto error_mutex;
- }
- if (pthread_mutex_init(&thread->threadIsReadyMutex, NULL) != 0)
- {
- WLog_ERR(TAG, "failed to initialize a mutex for a condition variable");
- goto error_thread_ready_mutex;
- }
- if (pthread_cond_init(&thread->threadIsReady, NULL) != 0)
- {
- WLog_ERR(TAG, "failed to initialize a condition variable");
- goto error_thread_ready;
- }
- WINPR_HANDLE_SET_TYPE_AND_MODE(thread, HANDLE_TYPE_THREAD, WINPR_FD_READ);
- handle = (HANDLE)thread;
- assert(handle != THREAD_CUR_ONE_HANDLE);
- if (!thread_list)
- {
- thread_list = ListDictionary_New(TRUE);
- if (!thread_list)
- {
- WLog_ERR(TAG, "Couldn't create global thread list");
- goto error_thread_list;
- }
- thread_list->objectKey.fnObjectEquals = thread_compare;
- }
- if (!(dwCreationFlags & CREATE_SUSPENDED))
- {
- if (!winpr_StartThread(thread))
- goto error_thread_list;
- }
- else
- {
- if (!set_event(thread))
- goto error_thread_list;
- }
- return handle;
- error_thread_list:
- pthread_cond_destroy(&thread->threadIsReady);
- error_thread_ready:
- pthread_mutex_destroy(&thread->threadIsReadyMutex);
- error_thread_ready_mutex:
- pthread_mutex_destroy(&thread->mutex);
- error_mutex:
- if (thread->pipe_fd[1] >= 0)
- close(thread->pipe_fd[1]);
- if (thread->pipe_fd[0] >= 0)
- close(thread->pipe_fd[0]);
- error_pipefd0:
- free(thread);
- return NULL;
- }
- void cleanup_handle(void* obj)
- {
- int rc;
- WINPR_THREAD* thread = (WINPR_THREAD*)obj;
- rc = pthread_cond_destroy(&thread->threadIsReady);
- if (rc)
- WLog_ERR(TAG, "failed to destroy a condition variable [%d] %s (%d)", rc, strerror(errno),
- errno);
- rc = pthread_mutex_destroy(&thread->threadIsReadyMutex);
- if (rc)
- WLog_ERR(TAG, "failed to destroy a condition variable mutex [%d] %s (%d)", rc,
- strerror(errno), errno);
- rc = pthread_mutex_destroy(&thread->mutex);
- if (rc)
- WLog_ERR(TAG, "failed to destroy mutex [%d] %s (%d)", rc, strerror(errno), errno);
- if (thread->pipe_fd[0] >= 0)
- close(thread->pipe_fd[0]);
- if (thread->pipe_fd[1] >= 0)
- close(thread->pipe_fd[1]);
- if (thread_list && ListDictionary_Contains(thread_list, &thread->thread))
- ListDictionary_Remove(thread_list, &thread->thread);
- #if defined(WITH_DEBUG_THREADS)
- if (thread->create_stack)
- winpr_backtrace_free(thread->create_stack);
- if (thread->exit_stack)
- winpr_backtrace_free(thread->exit_stack);
- #endif
- free(thread);
- }
- BOOL ThreadCloseHandle(HANDLE handle)
- {
- WINPR_THREAD* thread = (WINPR_THREAD*)handle;
- if (!thread_list)
- {
- WLog_ERR(TAG, "Thread list does not exist, check call!");
- dump_thread(thread);
- }
- else if (!ListDictionary_Contains(thread_list, &thread->thread))
- {
- WLog_ERR(TAG, "Thread list does not contain this thread! check call!");
- dump_thread(thread);
- }
- else
- {
- ListDictionary_Lock(thread_list);
- dump_thread(thread);
- if ((thread->started) && (WaitForSingleObject(thread, 0) != WAIT_OBJECT_0))
- {
- WLog_DBG(TAG, "Thread running, setting to detached state!");
- thread->detached = TRUE;
- pthread_detach(thread->thread);
- }
- else
- {
- cleanup_handle(thread);
- }
- ListDictionary_Unlock(thread_list);
- if (ListDictionary_Count(thread_list) < 1)
- {
- ListDictionary_Free(thread_list);
- thread_list = NULL;
- }
- }
- return TRUE;
- }
- HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes,
- SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
- {
- WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
- }
- VOID ExitThread(DWORD dwExitCode)
- {
- DWORD rc;
- pthread_t tid = pthread_self();
- if (!thread_list)
- {
- WLog_ERR(TAG, "%s called without existing thread list!", __FUNCTION__);
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- pthread_exit(0);
- }
- else if (!ListDictionary_Contains(thread_list, &tid))
- {
- WLog_ERR(TAG, "function called, but no matching entry in thread list!");
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- pthread_exit(0);
- }
- else
- {
- WINPR_THREAD* thread;
- ListDictionary_Lock(thread_list);
- thread = ListDictionary_GetItemValue(thread_list, &tid);
- assert(thread);
- thread->exited = TRUE;
- thread->dwExitCode = dwExitCode;
- #if defined(WITH_DEBUG_THREADS)
- thread->exit_stack = winpr_backtrace(20);
- #endif
- ListDictionary_Unlock(thread_list);
- set_event(thread);
- rc = thread->dwExitCode;
- if (thread->detached || !thread->started)
- cleanup_handle(thread);
- pthread_exit((void*)(size_t)rc);
- }
- }
- BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode)
- {
- ULONG Type;
- WINPR_HANDLE* Object;
- WINPR_THREAD* thread;
- if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
- return FALSE;
- thread = (WINPR_THREAD*)Object;
- *lpExitCode = thread->dwExitCode;
- return TRUE;
- }
- HANDLE _GetCurrentThread(VOID)
- {
- HANDLE hdl = THREAD_CUR_ONE_HANDLE;
- pthread_t tid = pthread_self();
- if (!thread_list)
- {
- WLog_ERR(TAG, "%s called without existing thread list!", __FUNCTION__);
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- }
- else if (!ListDictionary_Contains(thread_list, &tid))
- {
- WLog_ERR(TAG, "function called, but no matching entry in thread list!");
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- }
- else
- {
- hdl = ListDictionary_GetItemValue(thread_list, &tid);
- }
- return hdl;
- }
- DWORD GetCurrentThreadId(VOID)
- {
- pthread_t tid;
- tid = pthread_self();
- /* Since pthread_t can be 64-bits on some systems, take just the */
- /* lower 32-bits of it for the thread ID returned by this function. */
- return (DWORD)tid & 0xffffffffUL;
- }
- DWORD ResumeThread(HANDLE hThread)
- {
- ULONG Type;
- WINPR_HANDLE* Object;
- WINPR_THREAD* thread;
- if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
- return (DWORD)-1;
- thread = (WINPR_THREAD*)Object;
- if (pthread_mutex_lock(&thread->mutex))
- return (DWORD)-1;
- if (!thread->started)
- {
- if (!winpr_StartThread(thread))
- {
- pthread_mutex_unlock(&thread->mutex);
- return (DWORD)-1;
- }
- }
- else
- WLog_WARN(TAG, "Thread already started!");
- if (pthread_mutex_unlock(&thread->mutex))
- return (DWORD)-1;
- return 0;
- }
- DWORD SuspendThread(HANDLE hThread)
- {
- WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return (DWORD)-1;
- }
- BOOL SwitchToThread(VOID)
- {
- /**
- * Note: on some operating systems sched_yield is a stub returning -1.
- * usleep should at least trigger a context switch if any thread is waiting.
- */
- if (sched_yield() != 0)
- usleep(1);
- return TRUE;
- }
- BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode)
- {
- ULONG Type;
- WINPR_HANDLE* Object;
- WINPR_THREAD* thread;
- if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
- return FALSE;
- thread = (WINPR_THREAD*)Object;
- thread->exited = TRUE;
- thread->dwExitCode = dwExitCode;
- if (pthread_mutex_lock(&thread->mutex))
- return FALSE;
- #ifndef ANDROID
- pthread_cancel(thread->thread);
- #else
- WLog_ERR(TAG, "Function not supported on this platform!");
- #endif
- if (pthread_mutex_unlock(&thread->mutex))
- return FALSE;
- set_event(thread);
- return TRUE;
- }
- /*
- * Gifur add and implement it.
- */
- HANDLE OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId)
- {
- HANDLE hdl = NULL;
- pthread_t tid = (pthread_t)dwThreadId;
- if(bInheritHandle) {
- WLog_WARN(TAG, "bInheritHandle is not supported now.");
- }
- if (!thread_list)
- {
- WLog_ERR(TAG, "%s called without existing thread list!", __FUNCTION__);
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- }
- else if (!ListDictionary_Contains(thread_list, &tid))
- {
- WLog_ERR(TAG, "function called, but no matching entry in thread list!");
- #if defined(WITH_DEBUG_THREADS)
- DumpThreadHandles();
- #endif
- }
- else
- {
- hdl = ListDictionary_GetItemValue(thread_list, &tid);
- }
- return hdl;
- }
- /*Gifur implement and need to confirm its validity*/
- BOOL SetThreadPriority(HANDLE hThread, int nPriority)
- {
- BOOL result = TRUE;
- ULONG Type;
- WINPR_HANDLE* Object;
- WINPR_THREAD* thread = NULL;
- struct sched_param param;
- pthread_attr_t attr;
- pthread_t cur_thread;
- int policy = 0;
- int max_prio_for_policy = 0;
- int min_prio_for_policy = 0;
- int ret = 0;
- if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
- {
- if (hThread == THREAD_CUR_ONE_HANDLE) {
- WLog_DBG(TAG, "current thread flag.");
- cur_thread = pthread_self();
- }
- else {
- WLog_ERR(TAG, "get thread handle information failed!");
- return FALSE;
- }
- }
- else {
- thread = (WINPR_THREAD*)Object;
- cur_thread = thread->thread;
- }
- #if 0
- /*https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_setschedprio.html*/
- pthread_attr_init(&attr);
- pthread_attr_getschedpolicy(&attr, &policy);
- if (nPriority == THREAD_PRIORITY_HIGHEST) {
- max_prio_for_policy = sched_get_priority_max(policy);
- /*
- * set the scheduling priority for the thread to prio
- */
- if(0 != pthread_setschedprio(cur_thread, max_prio_for_policy)) {
- result = FALSE;
- }
- }
- pthread_attr_destroy(&attr);
- #else
- /*it might be preferable conceptually to solve this problem.*/
- ret = pthread_getschedparam(cur_thread, &policy, ¶m);
- if(0 != ret)
- {
- WLog_ERR(TAG, "get thread schedule param failed, err: %d", ret);
- return FALSE;
- }
- WLog_DBG(TAG, "the thread policy: %d, priority: %d.", policy, param.sched_priority);
- /*for scheduled under one of : SCHED_OTHER, SCHED_IDLE, SCHED_BATCH
- *sched_priority is not used and it must be 0.
- */
- if(policy == SCHED_OTHER
- #ifdef __USE_GNU
- || policy == SCHED_IDLE || policy == SCHED_BATCH
- #endif
- ) {
- policy = SCHED_FIFO;
- }
- max_prio_for_policy = sched_get_priority_max(policy);
- min_prio_for_policy = sched_get_priority_min(policy);
- if (nPriority == THREAD_PRIORITY_HIGHEST) {
- param.sched_priority = max_prio_for_policy;
- } else if (nPriority == THREAD_PRIORITY_ABOVE_NORMAL) {
- param.sched_priority = (max_prio_for_policy + min_prio_for_policy) / 2;
- } else
- {
- WLog_ERR(TAG, "current priority %d is not support!", nPriority);
- return FALSE;
- }
- /*
- * EPERM:
- * the caller does not have appropriate permission to set either the scheduling
- * parameters or the scheduling policy of the specified thread.
- */
- ret = pthread_setschedparam(cur_thread, policy, ¶m);
- if (0 != ret) {
- WLog_ERR(TAG, "set scheduled param failed! policy: %d, priority: %d, err: %d",
- policy, param.sched_priority, ret);
- result = FALSE;
- }
- #endif
- return result;
- }
- #if defined(WITH_DEBUG_THREADS)
- VOID DumpThreadHandles(void)
- {
- char** msg;
- size_t used, i;
- void* stack = winpr_backtrace(20);
- WLog_DBG(TAG, "---------------- Called from ----------------------------");
- msg = winpr_backtrace_symbols(stack, &used);
- for (i = 0; i < used; i++)
- {
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- }
- free(msg);
- winpr_backtrace_free(stack);
- WLog_DBG(TAG, "---------------- Start Dumping thread handles -----------");
- if (!thread_list)
- {
- WLog_DBG(TAG, "All threads properly shut down and disposed of.");
- }
- else
- {
- ULONG_PTR* keys = NULL;
- ListDictionary_Lock(thread_list);
- int x, count = ListDictionary_GetKeys(thread_list, &keys);
- WLog_DBG(TAG, "Dumping %d elements", count);
- for (x = 0; x < count; x++)
- {
- WINPR_THREAD* thread = ListDictionary_GetItemValue(thread_list, (void*)keys[x]);
- WLog_DBG(TAG, "Thread [%d] handle created still not closed!", x);
- msg = winpr_backtrace_symbols(thread->create_stack, &used);
- for (i = 0; i < used; i++)
- {
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- }
- free(msg);
- if (thread->started)
- {
- WLog_DBG(TAG, "Thread [%d] still running!", x);
- }
- else
- {
- WLog_DBG(TAG, "Thread [%d] exited at:", x);
- msg = winpr_backtrace_symbols(thread->exit_stack, &used);
- for (i = 0; i < used; i++)
- WLog_DBG(TAG, "[%" PRIdz "]: %s", i, msg[i]);
- free(msg);
- }
- }
- free(keys);
- ListDictionary_Unlock(thread_list);
- }
- WLog_DBG(TAG, "---------------- End Dumping thread handles -------------");
- }
- #endif
- #endif
|