mirror of https://github.com/FreeRDP/FreeRDP
winpr: several pool and synch fixes
pool: - the winpr implementation fallback was not used on older windows editions - drop useless and conflicting TP_CALLBACK_ENVIRON_V3 - fix race conditions by using use proper one-time initialization - on win32 WinPR tried to load several pool/callback_environment functions from kernel32.dll but since these are defined as inline functions in the windows headers, no windows edition has ever exported them in any dll. - removed callback_environment.c and added corresponding static inline function to pool.h - fix segfault in TestPoolWork: CloseThreadpoolWork() must not be called if there is a cleanup group associated with the work object since calling CloseThreadpoolCleanupGroupMember() already releases the work object sync: - The windows headers incorrectly define InitializeCriticalEx support if _WIN32_WINNT >= 0x0403 instead of >= 0x0600 (Vista) - created a compatible define to deal with this issue
This commit is contained in:
parent
8ea8b7c780
commit
c16bee759f
|
@ -36,15 +36,6 @@ typedef VOID (*PTP_SIMPLE_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Contex
|
|||
|
||||
typedef struct _TP_POOL TP_POOL, *PTP_POOL;
|
||||
|
||||
typedef enum _TP_CALLBACK_PRIORITY
|
||||
{
|
||||
TP_CALLBACK_PRIORITY_HIGH,
|
||||
TP_CALLBACK_PRIORITY_NORMAL,
|
||||
TP_CALLBACK_PRIORITY_LOW,
|
||||
TP_CALLBACK_PRIORITY_INVALID,
|
||||
TP_CALLBACK_PRIORITY_COUNT = TP_CALLBACK_PRIORITY_INVALID
|
||||
} TP_CALLBACK_PRIORITY;
|
||||
|
||||
typedef struct _TP_POOL_STACK_INFORMATION
|
||||
{
|
||||
SIZE_T StackReserve;
|
||||
|
@ -77,40 +68,9 @@ typedef struct _TP_CALLBACK_ENVIRON_V1
|
|||
} u;
|
||||
} TP_CALLBACK_ENVIRON_V1;
|
||||
|
||||
#endif
|
||||
typedef TP_CALLBACK_ENVIRON_V1 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
|
||||
|
||||
/* Non-Windows and pre Windows 7 */
|
||||
#if ((!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0601)))
|
||||
|
||||
typedef struct _TP_CALLBACK_ENVIRON_V3
|
||||
{
|
||||
TP_VERSION Version;
|
||||
PTP_POOL Pool;
|
||||
PTP_CLEANUP_GROUP CleanupGroup;
|
||||
PTP_CLEANUP_GROUP_CANCEL_CALLBACK CleanupGroupCancelCallback;
|
||||
PVOID RaceDll;
|
||||
struct _ACTIVATION_CONTEXT *ActivationContext;
|
||||
PTP_SIMPLE_CALLBACK FinalizationCallback;
|
||||
|
||||
union
|
||||
{
|
||||
DWORD Flags;
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD LongFunction:1;
|
||||
DWORD Persistent:1;
|
||||
DWORD Private:30;
|
||||
} s;
|
||||
} u;
|
||||
|
||||
TP_CALLBACK_PRIORITY CallbackPriority;
|
||||
DWORD Size;
|
||||
} TP_CALLBACK_ENVIRON_V3;
|
||||
|
||||
//typedef TP_CALLBACK_ENVIRON_V3 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
|
||||
|
||||
#endif
|
||||
#endif /* _WIN32 not defined */
|
||||
|
||||
typedef struct _TP_WORK TP_WORK, *PTP_WORK;
|
||||
typedef struct _TP_TIMER TP_TIMER, *PTP_TIMER;
|
||||
|
@ -120,9 +80,6 @@ typedef struct _TP_WAIT TP_WAIT, *PTP_WAIT;
|
|||
|
||||
typedef struct _TP_IO TP_IO, *PTP_IO;
|
||||
|
||||
#if !defined(_WIN32) || (defined(_WIN32) && (_WIN32_WINNT < 0x0601))
|
||||
typedef TP_CALLBACK_ENVIRON_V1 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
@ -153,7 +110,7 @@ typedef VOID (*PTP_WIN32_IO_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Cont
|
|||
|
||||
#endif
|
||||
|
||||
#if (!defined(_WIN32) || ((defined(_WIN32) && (_WIN32_WINNT < 0x0601))))
|
||||
#if (!defined(_WIN32) || ((defined(_WIN32) && (_WIN32_WINNT < 0x0600))))
|
||||
#define WINPR_THREAD_POOL 1
|
||||
#endif
|
||||
|
||||
|
@ -209,14 +166,44 @@ WINPR_API VOID SetThreadpoolThreadMaximum(PTP_POOL ptpp, DWORD cthrdMost);
|
|||
|
||||
/* Callback Environment */
|
||||
|
||||
WINPR_API VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
|
||||
WINPR_API VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
|
||||
WINPR_API VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp);
|
||||
WINPR_API VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe,
|
||||
PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng);
|
||||
WINPR_API VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe);
|
||||
WINPR_API VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod);
|
||||
WINPR_API VOID SetThreadpoolCallbackPriority(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority);
|
||||
static INLINE VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
pcbe->Version = 1;
|
||||
pcbe->Pool = NULL;
|
||||
pcbe->CleanupGroup = NULL;
|
||||
pcbe->CleanupGroupCancelCallback = NULL;
|
||||
pcbe->RaceDll = NULL;
|
||||
pcbe->ActivationContext = NULL;
|
||||
pcbe->FinalizationCallback = NULL;
|
||||
pcbe->u.Flags = 0;
|
||||
}
|
||||
|
||||
static INLINE VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
/* no actions, this may change in a future release. */
|
||||
}
|
||||
|
||||
static INLINE VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp)
|
||||
{
|
||||
pcbe->Pool = ptpp;
|
||||
}
|
||||
|
||||
static INLINE VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
|
||||
{
|
||||
pcbe->CleanupGroup = ptpcg;
|
||||
pcbe->CleanupGroupCancelCallback = pfng;
|
||||
}
|
||||
|
||||
static INLINE VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
pcbe->u.s.LongFunction = 1;
|
||||
}
|
||||
|
||||
static INLINE VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod)
|
||||
{
|
||||
pcbe->RaceDll = mod;
|
||||
}
|
||||
|
||||
|
||||
/* Callback */
|
||||
|
||||
|
|
|
@ -276,16 +276,8 @@ WINPR_API BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE Com
|
|||
|
||||
#endif
|
||||
|
||||
#if (defined(_WIN32) && defined(_SYNCHAPI_H_) && (_WIN32_WINNT < 0x0600))
|
||||
#define WINPR_INITIALIZE_CRITICAL_SECTION_EX 1
|
||||
#elif (defined(_WIN32) && (_WIN32_WINNT < 0x0403))
|
||||
#define WINPR_INITIALIZE_CRITICAL_SECTION_EX 1
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_INITIALIZE_CRITICAL_SECTION_EX
|
||||
|
||||
WINPR_API BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
|
||||
|
||||
#if (defined(_WIN32) && (_WIN32_WINNT < 0x0600))
|
||||
#define InitializeCriticalSectionEx(A,B,C) InitializeCriticalSectionAndSpinCount(A,B)
|
||||
#endif
|
||||
|
||||
#ifndef _RTL_RUN_ONCE_DEF
|
||||
|
|
|
@ -860,7 +860,7 @@ int UnixChangeFileMode(const char* filename, int flags)
|
|||
return -1;
|
||||
|
||||
/* Check for unsupported flags. */
|
||||
if (flags & ~(_S_IREAD | _S_IWRITE) != 0)
|
||||
if (flags & ~(_S_IREAD | _S_IWRITE))
|
||||
WLog_WARN(TAG, "Unsupported file mode %d for _wchmod", flags);
|
||||
|
||||
rc = _wchmod(wfl, flags);
|
||||
|
|
|
@ -23,7 +23,6 @@ winpr_module_add(
|
|||
cleanup_group.c
|
||||
pool.c
|
||||
pool.h
|
||||
callback_environment.c
|
||||
callback.c
|
||||
callback_cleanup.c)
|
||||
|
||||
|
|
|
@ -25,44 +25,32 @@
|
|||
#include <winpr/pool.h>
|
||||
#include <winpr/library.h>
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
|
||||
static BOOL (WINAPI * pCallbackMayRunLong)(PTP_CALLBACK_INSTANCE pci);
|
||||
|
||||
static void module_init()
|
||||
static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
|
||||
pCallbackMayRunLong = (void*) GetProcAddress(kernel32_module, "CallbackMayRunLong");
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32)
|
||||
{
|
||||
pCallbackMayRunLong = (void*)GetProcAddress(kernel32, "CallbackMayRunLong");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
BOOL CallbackMayRunLong(PTP_CALLBACK_INSTANCE pci)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCallbackMayRunLong)
|
||||
return pCallbackMayRunLong(pci);
|
||||
#else
|
||||
#endif
|
||||
/* No default implementation */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* WINPR_THREAD_POOL defined */
|
||||
|
|
|
@ -27,12 +27,10 @@
|
|||
|
||||
#include "pool.h"
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
|
||||
static VOID (WINAPI * pSetEventWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE evt);
|
||||
static VOID (WINAPI * pReleaseSemaphoreWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE sem, DWORD crel);
|
||||
static VOID (WINAPI * pReleaseMutexWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE mut);
|
||||
|
@ -40,96 +38,98 @@ static VOID (WINAPI * pLeaveCriticalSectionWhenCallbackReturns)(PTP_CALLBACK_INS
|
|||
static VOID (WINAPI * pFreeLibraryWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HMODULE mod);
|
||||
static VOID (WINAPI * pDisassociateCurrentThreadFromCallback)(PTP_CALLBACK_INSTANCE pci);
|
||||
|
||||
static void module_init()
|
||||
static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
|
||||
pSetEventWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "SetEventWhenCallbackReturns");
|
||||
pReleaseSemaphoreWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "ReleaseSemaphoreWhenCallbackReturns");
|
||||
pReleaseMutexWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "ReleaseMutexWhenCallbackReturns");
|
||||
pLeaveCriticalSectionWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "LeaveCriticalSectionWhenCallbackReturns");
|
||||
pFreeLibraryWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "FreeLibraryWhenCallbackReturns");
|
||||
pDisassociateCurrentThreadFromCallback = (void*) GetProcAddress(kernel32_module, "DisassociateCurrentThreadFromCallback");
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32)
|
||||
{
|
||||
pSetEventWhenCallbackReturns = (void*)GetProcAddress(kernel32, "SetEventWhenCallbackReturns");
|
||||
pReleaseSemaphoreWhenCallbackReturns = (void*)GetProcAddress(kernel32, "ReleaseSemaphoreWhenCallbackReturns");
|
||||
pReleaseMutexWhenCallbackReturns = (void*)GetProcAddress(kernel32, "ReleaseMutexWhenCallbackReturns");
|
||||
pLeaveCriticalSectionWhenCallbackReturns = (void*)GetProcAddress(kernel32, "LeaveCriticalSectionWhenCallbackReturns");
|
||||
pFreeLibraryWhenCallbackReturns = (void*)GetProcAddress(kernel32, "FreeLibraryWhenCallbackReturns");
|
||||
pDisassociateCurrentThreadFromCallback = (void*)GetProcAddress(kernel32, "DisassociateCurrentThreadFromCallback");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
VOID SetEventWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE evt)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pSetEventWhenCallbackReturns)
|
||||
{
|
||||
pSetEventWhenCallbackReturns(pci, evt);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID ReleaseSemaphoreWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE sem, DWORD crel)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pReleaseSemaphoreWhenCallbackReturns)
|
||||
{
|
||||
pReleaseSemaphoreWhenCallbackReturns(pci, sem, crel);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID ReleaseMutexWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE mut)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pReleaseMutexWhenCallbackReturns)
|
||||
{
|
||||
pReleaseMutexWhenCallbackReturns(pci, mut);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID LeaveCriticalSectionWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, PCRITICAL_SECTION pcs)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pLeaveCriticalSectionWhenCallbackReturns)
|
||||
{
|
||||
pLeaveCriticalSectionWhenCallbackReturns(pci, pcs);
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID FreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HMODULE mod)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pFreeLibraryWhenCallbackReturns)
|
||||
{
|
||||
pFreeLibraryWhenCallbackReturns(pci, mod);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID DisassociateCurrentThreadFromCallback(PTP_CALLBACK_INSTANCE pci)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pDisassociateCurrentThreadFromCallback)
|
||||
{
|
||||
pDisassociateCurrentThreadFromCallback(pci);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* WINPR_THREAD_POOL defined */
|
||||
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Thread Pool API (Callback Environment)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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 <winpr/crt.h>
|
||||
#include <winpr/pool.h>
|
||||
#include <winpr/library.h>
|
||||
|
||||
#include "pool.h"
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
VOID InitializeCallbackEnvironment_V1(TP_CALLBACK_ENVIRON_V1* pcbe)
|
||||
{
|
||||
pcbe->Version = 1;
|
||||
|
||||
pcbe->Pool = NULL;
|
||||
pcbe->CleanupGroup = NULL;
|
||||
pcbe->CleanupGroupCancelCallback = NULL;
|
||||
pcbe->RaceDll = NULL;
|
||||
pcbe->ActivationContext = NULL;
|
||||
pcbe->FinalizationCallback = NULL;
|
||||
pcbe->u.Flags = 0;
|
||||
}
|
||||
|
||||
VOID InitializeCallbackEnvironment_V3(TP_CALLBACK_ENVIRON_V3* pcbe)
|
||||
{
|
||||
pcbe->Version = 3;
|
||||
|
||||
pcbe->Pool = NULL;
|
||||
pcbe->CleanupGroup = NULL;
|
||||
pcbe->CleanupGroupCancelCallback = NULL;
|
||||
pcbe->RaceDll = NULL;
|
||||
pcbe->ActivationContext = NULL;
|
||||
pcbe->FinalizationCallback = NULL;
|
||||
pcbe->u.Flags = 0;
|
||||
|
||||
pcbe->CallbackPriority = TP_CALLBACK_PRIORITY_NORMAL;
|
||||
pcbe->Size = sizeof(TP_CALLBACK_ENVIRON);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static VOID (WINAPI * pDestroyThreadpoolEnvironment)(PTP_CALLBACK_ENVIRON pcbe);
|
||||
static VOID (WINAPI * pSetThreadpoolCallbackPool)(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp);
|
||||
static VOID (WINAPI * pSetThreadpoolCallbackCleanupGroup)(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng);
|
||||
static VOID (WINAPI * pSetThreadpoolCallbackRunsLong)(PTP_CALLBACK_ENVIRON pcbe);
|
||||
static VOID (WINAPI * pSetThreadpoolCallbackLibrary)(PTP_CALLBACK_ENVIRON pcbe, PVOID mod);
|
||||
static VOID (WINAPI * pSetThreadpoolCallbackPriority)(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority);
|
||||
|
||||
static void module_init()
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
|
||||
/* InitializeThreadpoolEnvironment is an inline function */
|
||||
pDestroyThreadpoolEnvironment = (void*) GetProcAddress(kernel32_module, "DestroyThreadpoolEnvironment");
|
||||
pSetThreadpoolCallbackPool = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackPool");
|
||||
pSetThreadpoolCallbackCleanupGroup = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackCleanupGroup");
|
||||
pSetThreadpoolCallbackRunsLong = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackRunsLong");
|
||||
pSetThreadpoolCallbackRunsLong = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackRunsLong");
|
||||
pSetThreadpoolCallbackLibrary = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackLibrary");
|
||||
pSetThreadpoolCallbackPriority = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackPriority");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static TP_CALLBACK_ENVIRON DEFAULT_CALLBACK_ENVIRONMENT =
|
||||
{
|
||||
1, /* Version */
|
||||
NULL, /* Pool */
|
||||
NULL, /* CleanupGroup */
|
||||
NULL, /* CleanupGroupCancelCallback */
|
||||
NULL, /* RaceDll */
|
||||
NULL, /* ActivationContext */
|
||||
NULL, /* FinalizationCallback */
|
||||
{ 0 } /* Flags */
|
||||
};
|
||||
|
||||
PTP_CALLBACK_ENVIRON GetDefaultThreadpoolEnvironment()
|
||||
{
|
||||
PTP_CALLBACK_ENVIRON environment = &DEFAULT_CALLBACK_ENVIRONMENT;
|
||||
|
||||
environment->Pool = GetDefaultThreadpool();
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
if (pcbe->Version == 3)
|
||||
InitializeCallbackEnvironment_V3((TP_CALLBACK_ENVIRON_V3*) pcbe);
|
||||
else
|
||||
InitializeCallbackEnvironment_V1(pcbe);
|
||||
}
|
||||
|
||||
VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pDestroyThreadpoolEnvironment)
|
||||
pDestroyThreadpoolEnvironment(pcbe);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSetThreadpoolCallbackPool)
|
||||
pSetThreadpoolCallbackPool(pcbe, ptpp);
|
||||
#else
|
||||
pcbe->Pool = ptpp;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSetThreadpoolCallbackCleanupGroup)
|
||||
pSetThreadpoolCallbackCleanupGroup(pcbe, ptpcg, pfng);
|
||||
#else
|
||||
pcbe->CleanupGroup = ptpcg;
|
||||
pcbe->CleanupGroupCancelCallback = pfng;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSetThreadpoolCallbackRunsLong)
|
||||
pSetThreadpoolCallbackRunsLong(pcbe);
|
||||
#else
|
||||
pcbe->u.s.LongFunction = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSetThreadpoolCallbackLibrary)
|
||||
pSetThreadpoolCallbackLibrary(pcbe, mod);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID SetThreadpoolCallbackPriority(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSetThreadpoolCallbackPriority)
|
||||
pSetThreadpoolCallbackPriority(pcbe, Priority);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -27,75 +27,64 @@
|
|||
|
||||
#include "pool.h"
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
|
||||
static PTP_CLEANUP_GROUP (WINAPI * pCreateThreadpoolCleanupGroup)();
|
||||
static VOID (WINAPI * pCloseThreadpoolCleanupGroupMembers)(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext);
|
||||
static VOID (WINAPI * pCloseThreadpoolCleanupGroup)(PTP_CLEANUP_GROUP ptpcg);
|
||||
|
||||
static void module_init()
|
||||
static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
|
||||
pCreateThreadpoolCleanupGroup = (void*) GetProcAddress(kernel32_module, "CreateThreadpoolCleanupGroup");
|
||||
pCloseThreadpoolCleanupGroupMembers = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolCleanupGroupMembers");
|
||||
pCloseThreadpoolCleanupGroup = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolCleanupGroup");
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32)
|
||||
{
|
||||
pCreateThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CreateThreadpoolCleanupGroup");
|
||||
pCloseThreadpoolCleanupGroupMembers = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroupMembers");
|
||||
pCloseThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroup");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if WINPR_THREAD_POOL
|
||||
|
||||
PTP_CLEANUP_GROUP CreateThreadpoolCleanupGroup()
|
||||
{
|
||||
PTP_CLEANUP_GROUP cleanupGroup = NULL;
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCreateThreadpoolCleanupGroup)
|
||||
return pCreateThreadpoolCleanupGroup();
|
||||
#else
|
||||
cleanupGroup = (PTP_CLEANUP_GROUP) malloc(sizeof(TP_CLEANUP_GROUP));
|
||||
#endif
|
||||
cleanupGroup = (PTP_CLEANUP_GROUP) malloc(sizeof(TP_CLEANUP_GROUP));
|
||||
return cleanupGroup;
|
||||
}
|
||||
|
||||
VOID CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCloseThreadpoolCleanupGroupMembers)
|
||||
{
|
||||
pCloseThreadpoolCleanupGroupMembers(ptpcg, fCancelPendingCallbacks, pvCleanupContext);
|
||||
#else
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* No default implementation */
|
||||
}
|
||||
|
||||
VOID CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCloseThreadpoolCleanupGroup)
|
||||
{
|
||||
pCloseThreadpoolCleanupGroup(ptpcg);
|
||||
#else
|
||||
free(ptpcg);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
free(ptpcg);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* WINPR_THREAD_POOL defined */
|
||||
|
||||
|
|
|
@ -27,37 +27,28 @@
|
|||
|
||||
#include "pool.h"
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
|
||||
static PTP_POOL (WINAPI * pCreateThreadpool)(PVOID reserved);
|
||||
static VOID (WINAPI * pCloseThreadpool)(PTP_POOL ptpp);
|
||||
static BOOL (WINAPI * pSetThreadpoolThreadMinimum)(PTP_POOL ptpp, DWORD cthrdMic);
|
||||
static VOID (WINAPI * pSetThreadpoolThreadMaximum)(PTP_POOL ptpp, DWORD cthrdMost);
|
||||
|
||||
static void module_init()
|
||||
static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
|
||||
pCreateThreadpool = (void*) GetProcAddress(kernel32_module, "CreateThreadpool");
|
||||
pCloseThreadpool = (void*) GetProcAddress(kernel32_module, "CloseThreadpool");
|
||||
pSetThreadpoolThreadMinimum = (void*) GetProcAddress(kernel32_module, "SetThreadpoolThreadMinimum");
|
||||
pSetThreadpoolThreadMaximum = (void*) GetProcAddress(kernel32_module, "SetThreadpoolThreadMaximum");
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32)
|
||||
{
|
||||
pCreateThreadpool = (void*)GetProcAddress(kernel32, "CreateThreadpool");
|
||||
pCloseThreadpool = (void*)GetProcAddress(kernel32, "CloseThreadpool");
|
||||
pSetThreadpoolThreadMinimum = (void*)GetProcAddress(kernel32, "SetThreadpoolThreadMinimum");
|
||||
pSetThreadpoolThreadMaximum = (void*)GetProcAddress(kernel32, "SetThreadpoolThreadMaximum");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
static TP_POOL DEFAULT_POOL =
|
||||
{
|
||||
|
@ -169,7 +160,6 @@ fail_countdown_event:
|
|||
fail_queue_new:
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
PTP_POOL GetDefaultThreadpool()
|
||||
|
@ -184,20 +174,14 @@ PTP_POOL GetDefaultThreadpool()
|
|||
return pool;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
PTP_POOL CreateThreadpool(PVOID reserved)
|
||||
{
|
||||
PTP_POOL pool = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCreateThreadpool)
|
||||
return pCreateThreadpool(reserved);
|
||||
#else
|
||||
#endif
|
||||
if (!(pool = (PTP_POOL) calloc(1, sizeof(TP_POOL))))
|
||||
return NULL;
|
||||
|
||||
|
@ -206,7 +190,6 @@ PTP_POOL CreateThreadpool(PVOID reserved)
|
|||
free(pool);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
@ -214,11 +197,13 @@ PTP_POOL CreateThreadpool(PVOID reserved)
|
|||
VOID CloseThreadpool(PTP_POOL ptpp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCloseThreadpool)
|
||||
{
|
||||
pCloseThreadpool(ptpp);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
SetEvent(ptpp->TerminateEvent);
|
||||
|
||||
ArrayList_Free(ptpp->Threads);
|
||||
|
@ -237,19 +222,16 @@ VOID CloseThreadpool(PTP_POOL ptpp)
|
|||
{
|
||||
free(ptpp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic)
|
||||
{
|
||||
HANDLE thread;
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pSetThreadpoolThreadMinimum)
|
||||
return pSetThreadpoolThreadMinimum(ptpp, cthrdMic);
|
||||
#else
|
||||
HANDLE thread;
|
||||
|
||||
#endif
|
||||
ptpp->Minimum = cthrdMic;
|
||||
|
||||
while (ArrayList_Count(ptpp->Threads) < ptpp->Minimum)
|
||||
|
@ -264,27 +246,21 @@ BOOL SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic)
|
|||
if (ArrayList_Add(ptpp->Threads, thread) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID SetThreadpoolThreadMaximum(PTP_POOL ptpp, DWORD cthrdMost)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pSetThreadpoolThreadMaximum)
|
||||
{
|
||||
pSetThreadpoolThreadMaximum(ptpp, cthrdMost);
|
||||
#else
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ptpp->Maximum = cthrdMost;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* dummy */
|
||||
|
||||
void winpr_pool_dummy()
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* WINPR_THREAD_POOL defined */
|
||||
|
|
|
@ -67,12 +67,7 @@ struct _TP_CLEANUP_GROUP
|
|||
void* dummy;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
PTP_POOL GetDefaultThreadpool(void);
|
||||
PTP_CALLBACK_ENVIRON GetDefaultThreadpoolEnvironment(void);
|
||||
|
||||
#endif
|
||||
PTP_POOL GetDefaultThreadpool();
|
||||
|
||||
#endif /* WINPR_POOL_PRIVATE_H */
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, P
|
|||
BYTE b[1024];
|
||||
BYTE c[1024];
|
||||
|
||||
printf("Hello %s: %d (thread: %d)\n", (char*) context,
|
||||
printf("Hello %s: %3d (thread: 0x%08X)\n", (char*) context,
|
||||
InterlockedIncrement(&count), GetCurrentThreadId());
|
||||
|
||||
for (index = 0; index < 100; index++)
|
||||
|
@ -104,7 +104,16 @@ int TestPoolWork(int argc, char* argv[])
|
|||
|
||||
DestroyThreadpoolEnvironment(&environment);
|
||||
|
||||
CloseThreadpoolWork(work);
|
||||
/**
|
||||
* See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx
|
||||
* If there is a cleanup group associated with the work object,
|
||||
* it is not necessary to call CloseThreadpoolWork !
|
||||
* calling the CloseThreadpoolCleanupGroupMembers function releases the work, wait,
|
||||
* and timer objects associated with the cleanup group.
|
||||
*/
|
||||
|
||||
/* CloseThreadpoolWork(work); // this would segfault, see comment above. */
|
||||
|
||||
CloseThreadpool(pool);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,92 +29,93 @@
|
|||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("pool")
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL module_initialized = FALSE;
|
||||
static BOOL module_available = FALSE;
|
||||
static HMODULE kernel32_module = NULL;
|
||||
|
||||
static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
|
||||
static PTP_WORK(WINAPI* pCreateThreadpoolWork)(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||
static VOID (WINAPI* pCloseThreadpoolWork)(PTP_WORK pwk);
|
||||
static VOID (WINAPI* pSubmitThreadpoolWork)(PTP_WORK pwk);
|
||||
static BOOL (WINAPI* pTrySubmitThreadpoolCallback)(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||
static VOID (WINAPI* pWaitForThreadpoolWorkCallbacks)(PTP_WORK pwk, BOOL fCancelPendingCallbacks);
|
||||
|
||||
static void module_init()
|
||||
static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
|
||||
{
|
||||
if (module_initialized)
|
||||
return;
|
||||
|
||||
kernel32_module = LoadLibraryA("kernel32.dll");
|
||||
module_initialized = TRUE;
|
||||
|
||||
if (!kernel32_module)
|
||||
return;
|
||||
|
||||
module_available = TRUE;
|
||||
pCreateThreadpoolWork = (void*) GetProcAddress(kernel32_module, "CreateThreadpoolWork");
|
||||
pCloseThreadpoolWork = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolWork");
|
||||
pSubmitThreadpoolWork = (void*) GetProcAddress(kernel32_module, "SubmitThreadpoolWork");
|
||||
pTrySubmitThreadpoolCallback = (void*) GetProcAddress(kernel32_module, "TrySubmitThreadpoolCallback");
|
||||
pWaitForThreadpoolWorkCallbacks = (void*) GetProcAddress(kernel32_module, "WaitForThreadpoolWorkCallbacks");
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32)
|
||||
{
|
||||
pCreateThreadpoolWork = (void*)GetProcAddress(kernel32, "CreateThreadpoolWork");
|
||||
pCloseThreadpoolWork = (void*)GetProcAddress(kernel32, "CloseThreadpoolWork");
|
||||
pSubmitThreadpoolWork = (void*)GetProcAddress(kernel32, "SubmitThreadpoolWork");
|
||||
pTrySubmitThreadpoolCallback = (void*)GetProcAddress(kernel32, "TrySubmitThreadpoolCallback");
|
||||
pWaitForThreadpoolWorkCallbacks = (void*)GetProcAddress(kernel32, "WaitForThreadpoolWorkCallbacks");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_THREAD_POOL
|
||||
static TP_CALLBACK_ENVIRON DEFAULT_CALLBACK_ENVIRONMENT =
|
||||
{
|
||||
1, /* Version */
|
||||
NULL, /* Pool */
|
||||
NULL, /* CleanupGroup */
|
||||
NULL, /* CleanupGroupCancelCallback */
|
||||
NULL, /* RaceDll */
|
||||
NULL, /* ActivationContext */
|
||||
NULL, /* FinalizationCallback */
|
||||
{ 0 } /* Flags */
|
||||
};
|
||||
|
||||
PTP_WORK CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
PTP_WORK work = NULL;
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCreateThreadpoolWork)
|
||||
return pCreateThreadpoolWork(pfnwk, pv, pcbe);
|
||||
|
||||
#else
|
||||
#endif
|
||||
work = (PTP_WORK) malloc(sizeof(TP_WORK));
|
||||
|
||||
if (work)
|
||||
{
|
||||
if (!pcbe)
|
||||
{
|
||||
pcbe = &DEFAULT_CALLBACK_ENVIRONMENT;
|
||||
pcbe->Pool = GetDefaultThreadpool();
|
||||
}
|
||||
work->CallbackEnvironment = pcbe;
|
||||
work->WorkCallback = pfnwk;
|
||||
work->CallbackParameter = pv;
|
||||
|
||||
if (!pcbe)
|
||||
pcbe = GetDefaultThreadpoolEnvironment();
|
||||
|
||||
work->CallbackEnvironment = pcbe;
|
||||
}
|
||||
|
||||
#endif
|
||||
return work;
|
||||
}
|
||||
|
||||
VOID CloseThreadpoolWork(PTP_WORK pwk)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pCloseThreadpoolWork)
|
||||
{
|
||||
pCloseThreadpoolWork(pwk);
|
||||
|
||||
#else
|
||||
free(pwk);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
free(pwk);
|
||||
}
|
||||
|
||||
VOID SubmitThreadpoolWork(PTP_WORK pwk)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pSubmitThreadpoolWork)
|
||||
pSubmitThreadpoolWork(pwk);
|
||||
|
||||
#else
|
||||
PTP_POOL pool;
|
||||
PTP_CALLBACK_INSTANCE callbackInstance;
|
||||
#ifdef _WIN32
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pSubmitThreadpoolWork)
|
||||
{
|
||||
pSubmitThreadpoolWork(pwk);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
pool = pwk->CallbackEnvironment->Pool;
|
||||
callbackInstance = (PTP_CALLBACK_INSTANCE) malloc(sizeof(TP_CALLBACK_INSTANCE));
|
||||
|
||||
|
@ -124,41 +125,36 @@ VOID SubmitThreadpoolWork(PTP_WORK pwk)
|
|||
CountdownEvent_AddCount(pool->WorkComplete, 1);
|
||||
Queue_Enqueue(pool->PendingQueue, callbackInstance);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pTrySubmitThreadpoolCallback)
|
||||
return pTrySubmitThreadpoolCallback(pfns, pv, pcbe);
|
||||
|
||||
#else
|
||||
#endif
|
||||
WLog_ERR(TAG, "TrySubmitThreadpoolCallback is not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, BOOL fCancelPendingCallbacks)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
module_init();
|
||||
|
||||
if (pWaitForThreadpoolWorkCallbacks)
|
||||
pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks);
|
||||
|
||||
#else
|
||||
HANDLE event;
|
||||
PTP_POOL pool;
|
||||
#ifdef _WIN32
|
||||
InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
|
||||
if (pWaitForThreadpoolWorkCallbacks)
|
||||
{
|
||||
pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
pool = pwk->CallbackEnvironment->Pool;
|
||||
event = CountdownEvent_WaitHandle(pool->WorkComplete);
|
||||
|
||||
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
|
||||
WLog_ERR(TAG, "error waiting on work completion");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* WINPR_THREAD_POOL defined */
|
||||
|
|
|
@ -247,48 +247,3 @@ VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_INITIALIZE_CRITICAL_SECTION_EX
|
||||
|
||||
typedef BOOL (WINAPI* PINITIALIZE_CRITICAL_SECTION_EX_FN)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
|
||||
|
||||
static HMODULE g_KERNEL32_Library = NULL;
|
||||
static BOOL g_InitializeCriticalSectionEx_Detected = FALSE;
|
||||
static BOOL g_InitializeCriticalSectionEx_Available = FALSE;
|
||||
static PINITIALIZE_CRITICAL_SECTION_EX_FN g_pInitializeCriticalSectionEx = NULL;
|
||||
|
||||
BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags)
|
||||
{
|
||||
if (!g_InitializeCriticalSectionEx_Detected)
|
||||
{
|
||||
g_KERNEL32_Library = LoadLibrary(_T("kernel32.dll"));
|
||||
|
||||
if (g_KERNEL32_Library)
|
||||
{
|
||||
g_pInitializeCriticalSectionEx = (PINITIALIZE_CRITICAL_SECTION_EX_FN)
|
||||
GetProcAddress(g_KERNEL32_Library, "InitializeCriticalSectionEx");
|
||||
g_InitializeCriticalSectionEx_Available = (g_pInitializeCriticalSectionEx) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_InitializeCriticalSectionEx_Available = FALSE;
|
||||
}
|
||||
|
||||
g_InitializeCriticalSectionEx_Detected = TRUE;
|
||||
}
|
||||
|
||||
if (g_InitializeCriticalSectionEx_Available)
|
||||
{
|
||||
/* Vista and later */
|
||||
return (*g_pInitializeCriticalSectionEx)(lpCriticalSection, dwSpinCount, Flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Windows XP */
|
||||
InitializeCriticalSection(lpCriticalSection);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue