Commit 3a7bc23a authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-9154 : Remove workarounds (mainly dynamic function loading)

for running obsolete versions of Windows
parent 22ede741
......@@ -50,7 +50,7 @@ IF(CMAKE_C_COMPILER MATCHES "icl")
ENDIF()
ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501)
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
# We do not want the windows.h macros min/max
ADD_DEFINITIONS(-DNOMINMAX)
# Speed up build process excluding unused header files
......
......@@ -27,7 +27,6 @@
#include <time.h>
#if defined(_WIN32)
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
#else
......
......@@ -54,26 +54,7 @@ typedef struct st_pthread_link {
We use native conditions on Vista and later, and fallback to own
implementation on earlier OS version.
*/
typedef union
{
/* Native condition (used on Vista and later) */
CONDITION_VARIABLE native_cond;
/* Own implementation (used on XP) */
struct
{
uint32 waiting;
CRITICAL_SECTION lock_waiting;
enum
{
SIGNAL= 0,
BROADCAST= 1,
MAX_EVENTS= 2
} EVENTS;
HANDLE events[MAX_EVENTS];
HANDLE broadcast_block_event;
};
} pthread_cond_t;
typedef CONDITION_VARIABLE pthread_cond_t;
typedef int pthread_mutexattr_t;
......@@ -81,10 +62,8 @@ typedef int pthread_mutexattr_t;
#define pthread_handler_t EXTERNC void * __cdecl
typedef void * (__cdecl *pthread_handler)(void *);
typedef volatile LONG my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT 0
#define MY_PTHREAD_ONCE_INPROGRESS 1
#define MY_PTHREAD_ONCE_DONE 2
typedef INIT_ONCE my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT;
#if !STRUCT_TIMESPEC_HAS_TV_SEC || !STRUCT_TIMESPEC_HAS_TV_NSEC
struct timespec {
......
......@@ -211,14 +211,6 @@ void vio_end(void);
#define SHUT_RD SD_RECEIVE
#endif
/*
Set thread id for io cancellation (required on Windows XP only,
and should to be removed if XP is no more supported)
*/
#define vio_set_thread_id(vio, tid) if(vio) vio->thread_id= tid
#else
#define vio_set_thread_id(vio, tid)
#endif
/* This enumerator is used in parser - should be always visible */
......@@ -288,7 +280,6 @@ struct st_vio
#ifdef _WIN32
HANDLE hPipe;
OVERLAPPED overlapped;
DWORD thread_id; /* Used on XP only by vio_shutdown() */
DWORD read_timeout_ms;
DWORD write_timeout_ms;
#endif
......
......@@ -1124,43 +1124,7 @@ static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs)
return 0;
}
#ifdef __WIN__
/*
This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
function if it is available, emulate it on NT4 Terminal Server by stripping
the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just
return GetSystemDirectory().
*/
typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT);
static size_t my_get_system_windows_directory(char *buffer, size_t size)
{
size_t count;
GET_SYSTEM_WINDOWS_DIRECTORY
func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY)
GetProcAddress(GetModuleHandle("kernel32.dll"),
"GetSystemWindowsDirectoryA");
if (func_ptr)
return func_ptr(buffer, (uint) size);
/*
Windows NT 4.0 Terminal Server Edition:
To retrieve the shared Windows directory, call GetSystemDirectory and
trim the "System32" element from the end of the returned path.
*/
count= GetSystemDirectory(buffer, (uint) size);
if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0)
{
count-= 8;
buffer[count] = '\0';
}
return count;
}
static const char *my_get_module_parent(char *buf, size_t size)
{
char *last= NULL;
......@@ -1209,7 +1173,7 @@ static const char **init_default_directories(MEM_ROOT *alloc)
{
char fname_buffer[FN_REFLEN];
if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer)))
if (GetSystemWindowsDirectory(fname_buffer, sizeof(fname_buffer)))
errors += add_directory(alloc, fname_buffer, dirs);
if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer)))
......
......@@ -26,63 +26,6 @@
#include <sys/timeb.h>
/*
Windows native condition variables. We use runtime loading / function
pointers, because they are not available on XP
*/
/* Prototypes and function pointers for condition variable functions */
typedef void (WINAPI * InitializeConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
typedef BOOL (WINAPI * SleepConditionVariableCSProc)
(PCONDITION_VARIABLE ConditionVariable,
PCRITICAL_SECTION CriticalSection,
DWORD dwMilliseconds);
typedef void (WINAPI * WakeAllConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
typedef void (WINAPI * WakeConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
static InitializeConditionVariableProc my_InitializeConditionVariable;
static SleepConditionVariableCSProc my_SleepConditionVariableCS;
static WakeAllConditionVariableProc my_WakeAllConditionVariable;
static WakeConditionVariableProc my_WakeConditionVariable;
/**
Indicates if we have native condition variables,
initialized first time pthread_cond_init is called.
*/
static BOOL have_native_conditions= FALSE;
/**
Check if native conditions can be used, load function pointers
*/
static void check_native_cond_availability(void)
{
HMODULE module= GetModuleHandle("kernel32");
my_InitializeConditionVariable= (InitializeConditionVariableProc)
GetProcAddress(module, "InitializeConditionVariable");
my_SleepConditionVariableCS= (SleepConditionVariableCSProc)
GetProcAddress(module, "SleepConditionVariableCS");
my_WakeAllConditionVariable= (WakeAllConditionVariableProc)
GetProcAddress(module, "WakeAllConditionVariable");
my_WakeConditionVariable= (WakeConditionVariableProc)
GetProcAddress(module, "WakeConditionVariable");
if (my_InitializeConditionVariable)
have_native_conditions= TRUE;
}
/**
Convert abstime to milliseconds
*/
......@@ -105,202 +48,40 @@ static DWORD get_milliseconds(const struct timespec *abstime)
return (DWORD)ms;
}
/*
Old (pre-vista) implementation using events
*/
static int legacy_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
cond->waiting= 0;
InitializeCriticalSection(&cond->lock_waiting);
cond->events[SIGNAL]= CreateEvent(NULL, /* no security */
FALSE, /* auto-reset event */
FALSE, /* non-signaled initially */
NULL); /* unnamed */
/* Create a manual-reset event. */
cond->events[BROADCAST]= CreateEvent(NULL, /* no security */
TRUE, /* manual-reset */
FALSE, /* non-signaled initially */
NULL); /* unnamed */
cond->broadcast_block_event= CreateEvent(NULL, /* no security */
TRUE, /* manual-reset */
TRUE, /* signaled initially */
NULL); /* unnamed */
if( cond->events[SIGNAL] == NULL ||
cond->events[BROADCAST] == NULL ||
cond->broadcast_block_event == NULL )
return ENOMEM;
return 0;
}
static int legacy_cond_destroy(pthread_cond_t *cond)
{
DeleteCriticalSection(&cond->lock_waiting);
if (CloseHandle(cond->events[SIGNAL]) == 0 ||
CloseHandle(cond->events[BROADCAST]) == 0 ||
CloseHandle(cond->broadcast_block_event) == 0)
return EINVAL;
return 0;
}
static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec *abstime)
{
int result;
DWORD timeout;
timeout= get_milliseconds(abstime);
/*
Block access if previous broadcast hasn't finished.
This is just for safety and should normally not
affect the total time spent in this function.
*/
WaitForSingleObject(cond->broadcast_block_event, INFINITE);
EnterCriticalSection(&cond->lock_waiting);
cond->waiting++;
LeaveCriticalSection(&cond->lock_waiting);
LeaveCriticalSection(mutex);
result= WaitForMultipleObjects(2, cond->events, FALSE, timeout);
EnterCriticalSection(&cond->lock_waiting);
cond->waiting--;
if (cond->waiting == 0)
{
/*
We're the last waiter to be notified or to stop waiting, so
reset the manual event.
*/
/* Close broadcast gate */
ResetEvent(cond->events[BROADCAST]);
/* Open block gate */
SetEvent(cond->broadcast_block_event);
}
LeaveCriticalSection(&cond->lock_waiting);
EnterCriticalSection(mutex);
return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
}
static int legacy_cond_signal(pthread_cond_t *cond)
{
EnterCriticalSection(&cond->lock_waiting);
if(cond->waiting > 0)
SetEvent(cond->events[SIGNAL]);
LeaveCriticalSection(&cond->lock_waiting);
return 0;
}
static int legacy_cond_broadcast(pthread_cond_t *cond)
{
EnterCriticalSection(&cond->lock_waiting);
/*
The mutex protect us from broadcasting if
there isn't any thread waiting to open the
block gate after this call has closed it.
*/
if(cond->waiting > 0)
{
/* Close block gate */
ResetEvent(cond->broadcast_block_event);
/* Open broadcast gate */
SetEvent(cond->events[BROADCAST]);
}
LeaveCriticalSection(&cond->lock_waiting);
return 0;
}
/*
Posix API functions. Just choose between native and legacy implementation.
*/
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
/*
Once initialization is used here rather than in my_init(), to
1) avoid my_init() pitfalls- undefined order in which initialization should
run
2) be potentially useful C++ (in static constructors that run before main())
3) just to simplify the API.
Also, the overhead of my_pthread_once is very small.
*/
static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT;
my_pthread_once(&once_control, check_native_cond_availability);
if (have_native_conditions)
{
my_InitializeConditionVariable(&cond->native_cond);
return 0;
}
else
return legacy_cond_init(cond, attr);
InitializeConditionVariable(cond);
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
if (have_native_conditions)
return 0; /* no destroy function */
else
return legacy_cond_destroy(cond);
return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
if (have_native_conditions)
{
my_WakeAllConditionVariable(&cond->native_cond);
return 0;
}
else
return legacy_cond_broadcast(cond);
WakeAllConditionVariable(cond);
return 0;
}
int pthread_cond_signal(pthread_cond_t *cond)
{
if (have_native_conditions)
{
my_WakeConditionVariable(&cond->native_cond);
return 0;
}
else
return legacy_cond_signal(cond);
WakeConditionVariable(cond);
return 0;
}
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime)
{
if (have_native_conditions)
{
DWORD timeout= get_milliseconds(abstime);
if (!my_SleepConditionVariableCS(&cond->native_cond, mutex, timeout))
return ETIMEDOUT;
return 0;
}
else
return legacy_cond_timedwait(cond, mutex, abstime);
DWORD timeout= get_milliseconds(abstime);
if (!SleepConditionVariableCS(cond, mutex, timeout))
return ETIMEDOUT;
return 0;
}
......
......@@ -149,45 +149,22 @@ int pthread_cancel(pthread_t thread)
return -1;
}
/*
One time initialization. For simplicity, we assume initializer thread
does not exit within init_routine().
One time initialization.
*/
int my_pthread_once(my_pthread_once_t *once_control,
void (*init_routine)(void))
{
LONG state;
/*
Do "dirty" read to find out if initialization is already done, to
save an interlocked operation in common case. Memory barriers are ensured by
Visual C++ volatile implementation.
*/
if (*once_control == MY_PTHREAD_ONCE_DONE)
return 0;
state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
MY_PTHREAD_ONCE_INIT);
static BOOL CALLBACK init_once_callback(my_pthread_once_t *once_control, PVOID param, PVOID *context)
{
typedef void(*void_f)(void);
((void_f)param)();
return TRUE;
}
switch(state)
{
case MY_PTHREAD_ONCE_INIT:
/* This is initializer thread */
(*init_routine)();
*once_control= MY_PTHREAD_ONCE_DONE;
break;
case MY_PTHREAD_ONCE_INPROGRESS:
/* init_routine in progress. Wait for its completion */
while(*once_control == MY_PTHREAD_ONCE_INPROGRESS)
{
Sleep(1);
}
break;
case MY_PTHREAD_ONCE_DONE:
/* Nothing to do */
break;
}
int my_pthread_once(my_pthread_once_t *once_control, void (*func)(void))
{
InitOnceExecuteOnce(once_control, init_once_callback, func, NULL);
return 0;
}
#endif
......@@ -4922,25 +4922,14 @@ static void end_ssl()
/**
Registers a file to be collected when Windows Error Reporting creates a crash
report.
@note only works on Vista and later, since WerRegisterFile() is not available
on earlier Windows.
*/
#include <werapi.h>
static void add_file_to_crash_report(char *file)
{
/* Load WerRegisterFile function dynamically.*/
HRESULT (WINAPI *pWerRegisterFile)(PCWSTR, WER_REGISTER_FILE_TYPE, DWORD)
=(HRESULT (WINAPI *) (PCWSTR, WER_REGISTER_FILE_TYPE, DWORD))
GetProcAddress(GetModuleHandle("kernel32"),"WerRegisterFile");
if (pWerRegisterFile)
wchar_t wfile[MAX_PATH+1]= {0};
if (mbstowcs(wfile, file, MAX_PATH) != (size_t)-1)
{
wchar_t wfile[MAX_PATH+1]= {0};
if (mbstowcs(wfile, file, MAX_PATH) != (size_t)-1)
{
pWerRegisterFile(wfile, WerRegFileTypeOther, WER_FILE_ANONYMOUS_DATA);
}
WerRegisterFile(wfile, WerRegFileTypeOther, WER_FILE_ANONYMOUS_DATA);
}
}
#endif
......@@ -9640,13 +9629,6 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
one_thread_scheduler(extra_thread_scheduler);
#else
#ifdef _WIN32
/* workaround: disable thread pool on XP */
if (GetProcAddress(GetModuleHandle("kernel32"),"CreateThreadpool") == 0 &&
thread_handling > SCHEDULER_NO_THREADS)
SYSVAR_AUTOSIZE(thread_handling, SCHEDULER_ONE_THREAD_PER_CONNECTION);
#endif
if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
one_thread_per_connection_scheduler(thread_scheduler, &max_connections,
&connection_count);
......
......@@ -2100,7 +2100,6 @@ bool THD::store_globals()
STACK_DIRECTION * (long)my_thread_stack_size;
if (net.vio)
{
vio_set_thread_id(net.vio, real_id);
net.thd= this;
}
/*
......
......@@ -2933,7 +2933,6 @@ class THD :public Statement,
{
mysql_mutex_lock(&LOCK_thd_data);
active_vio = vio;
vio_set_thread_id(vio, pthread_self());
mysql_mutex_unlock(&LOCK_thd_data);
}
inline void clear_active_vio()
......
......@@ -32,16 +32,6 @@
#include <windows.h>
/*
Threadpool API is not available on XP. We still want to compile a single
version on Windows, but use the latest functionality if available.
We cannot use threadpool functionality directly, since executable won't
start on XP and loader will complain about missing symbols.
We solve using the usual way it is done on Windows, i.e with dynamic loading.
We'll need to load a lot of function, and make this less painful with the
WEAK_SYMBOL macro below
*/
/*
WEAK_SYMBOL(return_type, function_name, argument_type1,..,argument_typeN)
......@@ -61,107 +51,10 @@
static pFN_##function my_##function = (pFN_##function) \
(GetProcAddress(GetModuleHandle("kernel32"),#function))
WEAK_SYMBOL(VOID, CancelThreadpoolIo, PTP_IO);
#define CancelThreadpoolIo my_CancelThreadpoolIo
WEAK_SYMBOL(VOID, CloseThreadpool, PTP_POOL);
#define CloseThreadpool my_CloseThreadpool
WEAK_SYMBOL(VOID, CloseThreadpoolIo, PTP_IO);
#define CloseThreadpoolIo my_CloseThreadpoolIo
WEAK_SYMBOL(VOID, CloseThreadpoolTimer,PTP_TIMER);
#define CloseThreadpoolTimer my_CloseThreadpoolTimer
WEAK_SYMBOL(VOID, CloseThreadpoolWait,PTP_WAIT);
#define CloseThreadpoolWait my_CloseThreadpoolWait
WEAK_SYMBOL(PTP_POOL, CreateThreadpool,PVOID);
#define CreateThreadpool my_CreateThreadpool
WEAK_SYMBOL(PTP_IO, CreateThreadpoolIo, HANDLE, PTP_WIN32_IO_CALLBACK, PVOID ,
PTP_CALLBACK_ENVIRON);
#define CreateThreadpoolIo my_CreateThreadpoolIo
WEAK_SYMBOL(PTP_TIMER, CreateThreadpoolTimer, PTP_TIMER_CALLBACK ,
PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
#define CreateThreadpoolTimer my_CreateThreadpoolTimer
WEAK_SYMBOL(PTP_WAIT, CreateThreadpoolWait, PTP_WAIT_CALLBACK, PVOID,
PTP_CALLBACK_ENVIRON);
#define CreateThreadpoolWait my_CreateThreadpoolWait
WEAK_SYMBOL(VOID, DisassociateCurrentThreadFromCallback, PTP_CALLBACK_INSTANCE);
#define DisassociateCurrentThreadFromCallback my_DisassociateCurrentThreadFromCallback
WEAK_SYMBOL(DWORD, FlsAlloc, PFLS_CALLBACK_FUNCTION);
#define FlsAlloc my_FlsAlloc
WEAK_SYMBOL(PVOID, FlsGetValue, DWORD);
#define FlsGetValue my_FlsGetValue
WEAK_SYMBOL(BOOL, FlsSetValue, DWORD, PVOID);
#define FlsSetValue my_FlsSetValue
WEAK_SYMBOL(VOID, SetThreadpoolThreadMaximum, PTP_POOL, DWORD);
#define SetThreadpoolThreadMaximum my_SetThreadpoolThreadMaximum
WEAK_SYMBOL(BOOL, SetThreadpoolThreadMinimum, PTP_POOL, DWORD);
#define SetThreadpoolThreadMinimum my_SetThreadpoolThreadMinimum
WEAK_SYMBOL(VOID, SetThreadpoolTimer, PTP_TIMER, PFILETIME,DWORD,DWORD);
#define SetThreadpoolTimer my_SetThreadpoolTimer
WEAK_SYMBOL(VOID, SetThreadpoolWait, PTP_WAIT,HANDLE,PFILETIME);
#define SetThreadpoolWait my_SetThreadpoolWait
WEAK_SYMBOL(VOID, StartThreadpoolIo, PTP_IO);
#define StartThreadpoolIo my_StartThreadpoolIo
WEAK_SYMBOL(VOID, WaitForThreadpoolIoCallbacks,PTP_IO, BOOL);
#define WaitForThreadpoolIoCallbacks my_WaitForThreadpoolIoCallbacks
WEAK_SYMBOL(VOID, WaitForThreadpoolTimerCallbacks, PTP_TIMER, BOOL);
#define WaitForThreadpoolTimerCallbacks my_WaitForThreadpoolTimerCallbacks
WEAK_SYMBOL(VOID, WaitForThreadpoolWaitCallbacks, PTP_WAIT, BOOL);
#define WaitForThreadpoolWaitCallbacks my_WaitForThreadpoolWaitCallbacks
WEAK_SYMBOL(BOOL, SetFileCompletionNotificationModes, HANDLE, UCHAR);
#define SetFileCompletionNotificationModes my_SetFileCompletionNotificationModes
WEAK_SYMBOL(BOOL, TrySubmitThreadpoolCallback, PTP_SIMPLE_CALLBACK pfns,
PVOID pv,PTP_CALLBACK_ENVIRON pcbe);
#define TrySubmitThreadpoolCallback my_TrySubmitThreadpoolCallback
WEAK_SYMBOL(PTP_WORK, CreateThreadpoolWork, PTP_WORK_CALLBACK pfnwk, PVOID pv,
PTP_CALLBACK_ENVIRON pcbe);
#define CreateThreadpoolWork my_CreateThreadpoolWork
WEAK_SYMBOL(VOID, SubmitThreadpoolWork,PTP_WORK pwk);
#define SubmitThreadpoolWork my_SubmitThreadpoolWork
WEAK_SYMBOL(VOID, CloseThreadpoolWork, PTP_WORK pwk);
#define CloseThreadpoolWork my_CloseThreadpoolWork
WEAK_SYMBOL(BOOL, CallbackMayRunLong, PTP_CALLBACK_INSTANCE pci);
#define CallbackMayRunLong my_CallbackMayRunLong
#if _MSC_VER >= 1600
/* Stack size manipulation available only on Win7+ /declarations in VS10 */
WEAK_SYMBOL(BOOL, SetThreadpoolStackInformation, PTP_POOL,
PTP_POOL_STACK_INFORMATION);
#define SetThreadpoolStackInformation my_SetThreadpoolStackInformation
#else /* _MSC_VER < 1600 */
#define SetThreadpoolCallbackPriority(env,prio)
typedef enum _TP_CALLBACK_PRIORITY {
TP_CALLBACK_PRIORITY_HIGH,
TP_CALLBACK_PRIORITY_NORMAL,
TP_CALLBACK_PRIORITY_LOW,
TP_CALLBACK_PRIORITY_INVALID
} TP_CALLBACK_PRIORITY;
#endif
/* Log a warning */
static void tp_log_warning(const char *msg, const char *fct)
......
......@@ -297,9 +297,6 @@ use simulated aio we build below with threads.
Currently we support native aio on windows and linux */
extern my_bool srv_use_native_aio;
extern my_bool srv_numa_interleave;
#ifdef __WIN__
extern ibool srv_use_native_conditions;
#endif /* __WIN__ */
#endif /* !UNIV_HOTBACKUP */
/* Use trim operation */
......
......@@ -85,31 +85,6 @@ event embedded inside a mutex, on free, this generates a recursive call.
This version of the free event function doesn't acquire the global lock */
static void os_event_free_internal(os_event_t event);
/* On Windows (Vista and later), load function pointers for condition
variable handling. Those functions are not available in prior versions,
so we have to use them via runtime loading, as long as we support XP. */
static void os_cond_module_init(void);
#ifdef __WIN__
/* Prototypes and function pointers for condition variable functions */
typedef VOID (WINAPI* InitializeConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
static InitializeConditionVariableProc initialize_condition_variable;
typedef BOOL (WINAPI* SleepConditionVariableCSProc)
(PCONDITION_VARIABLE ConditionVariable,
PCRITICAL_SECTION CriticalSection,
DWORD dwMilliseconds);
static SleepConditionVariableCSProc sleep_condition_variable;
typedef VOID (WINAPI* WakeAllConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
static WakeAllConditionVariableProc wake_all_condition_variable;
typedef VOID (WINAPI* WakeConditionVariableProc)
(PCONDITION_VARIABLE ConditionVariable);
static WakeConditionVariableProc wake_condition_variable;
#endif
/*********************************************************//**
Initialitze condition variable */
......@@ -122,8 +97,7 @@ os_cond_init(
ut_a(cond);
#ifdef __WIN__
ut_a(initialize_condition_variable != NULL);
initialize_condition_variable(cond);
InitializeConditionVariable(cond);
#else
ut_a(pthread_cond_init(cond, NULL) == 0);
#endif
......@@ -151,9 +125,8 @@ os_cond_wait_timed(
BOOL ret;
DWORD err;
ut_a(sleep_condition_variable != NULL);
ret = sleep_condition_variable(cond, mutex, time_in_ms);
ret = SleepConditionVariableCS(cond, mutex, time_in_ms);
if (!ret) {
err = GetLastError();
......@@ -208,8 +181,7 @@ os_cond_wait(
ut_a(mutex);
#ifdef __WIN__
ut_a(sleep_condition_variable != NULL);
ut_a(sleep_condition_variable(cond, mutex, INFINITE));
ut_a(SleepConditionVariableCS(cond, mutex, INFINITE));
#else
ut_a(pthread_cond_wait(cond, mutex) == 0);
#endif
......@@ -226,8 +198,7 @@ os_cond_broadcast(
ut_a(cond);
#ifdef __WIN__
ut_a(wake_all_condition_variable != NULL);
wake_all_condition_variable(cond);
WakeAllConditionVariable(cond);
#else
ut_a(pthread_cond_broadcast(cond) == 0);
#endif
......@@ -248,40 +219,6 @@ os_cond_destroy(
#endif
}
/*********************************************************//**
On Windows (Vista and later), load function pointers for condition variable
handling. Those functions are not available in prior versions, so we have to
use them via runtime loading, as long as we support XP. */
static
void
os_cond_module_init(void)
/*=====================*/
{
#ifdef __WIN__
HMODULE h_dll;
if (!srv_use_native_conditions)
return;
h_dll = GetModuleHandle("kernel32");
initialize_condition_variable = (InitializeConditionVariableProc)
GetProcAddress(h_dll, "InitializeConditionVariable");
sleep_condition_variable = (SleepConditionVariableCSProc)
GetProcAddress(h_dll, "SleepConditionVariableCS");
wake_all_condition_variable = (WakeAllConditionVariableProc)
GetProcAddress(h_dll, "WakeAllConditionVariable");
wake_condition_variable = (WakeConditionVariableProc)
GetProcAddress(h_dll, "WakeConditionVariable");
/* When using native condition variables, check function pointers */
ut_a(initialize_condition_variable);
ut_a(sleep_condition_variable);
ut_a(wake_all_condition_variable);
ut_a(wake_condition_variable);
#endif
}
/*********************************************************//**
Initializes global event and OS 'slow' mutex lists. */
UNIV_INTERN
......@@ -295,9 +232,6 @@ os_sync_init(void)
os_sync_mutex = NULL;
os_sync_mutex_inited = FALSE;
/* Now for Windows only */
os_cond_module_init();
os_sync_mutex = os_mutex_create();
os_sync_mutex_inited = TRUE;
......@@ -350,43 +284,27 @@ os_event_t
os_event_create(void)
/*==================*/
{
os_event_t event;
#ifdef __WIN__
if(!srv_use_native_conditions) {
event = static_cast<os_event_t>(ut_malloc(sizeof(*event)));
os_event_t event;
event->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!event->handle) {
fprintf(stderr,
"InnoDB: Could not create a Windows event"
" semaphore; Windows error %lu\n",
(ulong) GetLastError());
}
} else /* Windows with condition variables */
#endif
{
event = static_cast<os_event_t>(ut_malloc(sizeof *event));
event = static_cast<os_event_t>(ut_malloc(sizeof *event));
#ifndef PFS_SKIP_EVENT_MUTEX
os_fast_mutex_init(event_os_mutex_key, &event->os_mutex);
os_fast_mutex_init(event_os_mutex_key, &event->os_mutex);
#else
os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &event->os_mutex);
os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &event->os_mutex);
#endif
os_cond_init(&(event->cond_var));
os_cond_init(&(event->cond_var));
event->is_set = FALSE;
event->is_set = FALSE;
/* We return this value in os_event_reset(), which can then be
be used to pass to the os_event_wait_low(). The value of zero
is reserved in os_event_wait_low() for the case when the
caller does not want to pass any signal_count value. To
distinguish between the two cases we initialize signal_count
to 1 here. */
event->signal_count = 1;
}
/* We return this value in os_event_reset(), which can then be
be used to pass to the os_event_wait_low(). The value of zero
is reserved in os_event_wait_low() for the case when the
caller does not want to pass any signal_count value. To
distinguish between the two cases we initialize signal_count
to 1 here. */
event->signal_count = 1;
/* The os_sync_mutex can be NULL because during startup an event
can be created [ because it's embedded in the mutex/rwlock ] before
......@@ -418,13 +336,6 @@ os_event_set(
{
ut_a(event);
#ifdef __WIN__
if (!srv_use_native_conditions) {
ut_a(SetEvent(event->handle));
return;
}
#endif
os_fast_mutex_lock(&(event->os_mutex));
if (event->is_set) {
......@@ -456,13 +367,6 @@ os_event_reset(
ut_a(event);
#ifdef __WIN__
if(!srv_use_native_conditions) {
ut_a(ResetEvent(event->handle));
return(0);
}
#endif
os_fast_mutex_lock(&(event->os_mutex));
if (!event->is_set) {
......@@ -484,20 +388,13 @@ os_event_free_internal(
/*===================*/
os_event_t event) /*!< in: event to free */
{
#ifdef __WIN__
if(!srv_use_native_conditions) {
ut_a(event);
ut_a(CloseHandle(event->handle));
} else
#endif
{
ut_a(event);
/* This is to avoid freeing the mutex twice */
os_fast_mutex_free(&(event->os_mutex));
ut_a(event);
os_cond_destroy(&(event->cond_var));
}
/* This is to avoid freeing the mutex twice */
os_fast_mutex_free(&(event->os_mutex));
os_cond_destroy(&(event->cond_var));
/* Remove from the list of events */
UT_LIST_REMOVE(os_event_list, os_event_list, event);
......@@ -517,16 +414,10 @@ os_event_free(
{
ut_a(event);
#ifdef __WIN__
if(!srv_use_native_conditions){
ut_a(CloseHandle(event->handle));
} else /*Windows with condition variables */
#endif
{
os_fast_mutex_free(&(event->os_mutex));
os_cond_destroy(&(event->cond_var));
}
os_fast_mutex_free(&(event->os_mutex));
os_cond_destroy(&(event->cond_var));
/* Remove from the list of events */
os_mutex_enter(os_sync_mutex);
......@@ -566,21 +457,6 @@ os_event_wait_low(
returned by previous call of
os_event_reset(). */
{
#ifdef __WIN__
if(!srv_use_native_conditions) {
DWORD err;
ut_a(event);
UT_NOT_USED(reset_sig_count);
/* Specify an infinite wait */
err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0);
return;
}
#endif
os_fast_mutex_lock(&event->os_mutex);
......@@ -619,36 +495,10 @@ os_event_wait_time_low(
#ifdef __WIN__
DWORD time_in_ms;
if (!srv_use_native_conditions) {
DWORD err;
ut_a(event);
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
time_in_ms = static_cast<DWORD>(time_in_usec / 1000);
err = WaitForSingleObject(event->handle, time_in_ms);
} else {
err = WaitForSingleObject(event->handle, INFINITE);
}
if (err == WAIT_OBJECT_0) {
return(0);
} else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
return(OS_SYNC_TIME_EXCEEDED);
}
ut_error;
/* Dummy value to eliminate compiler warning. */
return(42);
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
time_in_ms = static_cast<DWORD>(time_in_usec / 1000);
} else {
ut_a(sleep_condition_variable != NULL);
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
time_in_ms = static_cast<DWORD>(time_in_usec / 1000);
} else {
time_in_ms = INFINITE;
}
time_in_ms = INFINITE;
}
#else
struct timespec abstime;
......
......@@ -1836,32 +1836,7 @@ innobase_start_or_create_for_mysql(void)
srv_startup_is_before_trx_rollback_phase = TRUE;
#ifdef __WIN__
switch (os_get_os_version()) {
case OS_WIN95:
case OS_WIN31:
case OS_WINNT:
srv_use_native_conditions = FALSE;
/* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
and NT use simulated aio. In NT Windows provides async i/o,
but when run in conjunction with InnoDB Hot Backup, it seemed
to corrupt the data files. */
srv_use_native_aio = FALSE;
break;
case OS_WIN2000:
case OS_WINXP:
/* On 2000 and XP, async IO is available, but no condition variables. */
srv_use_native_aio = TRUE;
srv_use_native_conditions = FALSE;
break;
default:
/* Vista and later have both async IO and condition variables */
srv_use_native_aio = TRUE;
srv_use_native_conditions = TRUE;
break;
}
srv_use_native_aio = TRUE;
#elif defined(LINUX_NATIVE_AIO)
......
......@@ -67,7 +67,7 @@ int vio_shared_memory_shutdown(Vio *vio, int how)
int vio_pipe_shutdown(Vio *vio, int how)
{
return cancel_io(vio->hPipe, vio->thread_id);
return CancelIoEx(vio->hPipe, NULL);
}
#endif
......
......@@ -299,59 +299,12 @@ size_t vio_write(Vio *vio, const uchar* buf, size_t size)
DBUG_RETURN(ret);
}
#ifdef _WIN32
static void CALLBACK cancel_io_apc(ULONG_PTR data)
{
CancelIo((HANDLE)data);
}
/*
Cancel IO on Windows.
On XP, issue CancelIo as asynchronous procedure call to the thread
that started IO. On Vista+, simpler cancelation is done with
CancelIoEx.
*/
int cancel_io(HANDLE handle, DWORD thread_id)
{
static BOOL (WINAPI *fp_CancelIoEx) (HANDLE, OVERLAPPED *);
static volatile int first_time= 1;
int rc;
HANDLE thread_handle;
if (first_time)
{
/* Try to load CancelIoEx using GetProcAddress */
InterlockedCompareExchangePointer((volatile void *)&fp_CancelIoEx,
GetProcAddress(GetModuleHandle("kernel32"), "CancelIoEx"), NULL);
first_time =0;
}
if (fp_CancelIoEx)
{
return fp_CancelIoEx(handle, NULL)? 0 :-1;
}
thread_handle= OpenThread(THREAD_SET_CONTEXT, FALSE, thread_id);
if (thread_handle)
{
rc= QueueUserAPC(cancel_io_apc, thread_handle, (ULONG_PTR)handle);
CloseHandle(thread_handle);
}
return rc;
}
#endif
int vio_socket_shutdown(Vio *vio, int how)
{
int ret= shutdown(mysql_socket_getfd(vio->mysql_socket), how);
#ifdef _WIN32
/* Cancel possible IO in progress (shutdown does not do that on Windows). */
(void) cancel_io((HANDLE) mysql_socket_getfd(vio->mysql_socket),
vio->thread_id);
(void) CancelIoEx((HANDLE)mysql_socket_getfd(vio->mysql_socket), NULL);
#endif
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment