mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Backport fix for MySQL bug #56405 :
use native windows condition variables and rwlocks in mysys, if Windows supports it.
This commit is contained in:
parent
824ce5f3ea
commit
fe054adfca
6 changed files with 450 additions and 98 deletions
|
@ -48,19 +48,30 @@ typedef struct st_pthread_link {
|
|||
struct st_pthread_link *next;
|
||||
} pthread_link;
|
||||
|
||||
typedef struct {
|
||||
uint32 waiting;
|
||||
CRITICAL_SECTION lock_waiting;
|
||||
|
||||
enum {
|
||||
SIGNAL= 0,
|
||||
BROADCAST= 1,
|
||||
MAX_EVENTS= 2
|
||||
} EVENTS;
|
||||
|
||||
HANDLE events[MAX_EVENTS];
|
||||
HANDLE broadcast_block_event;
|
||||
/**
|
||||
Implementation of Windows condition variables.
|
||||
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;
|
||||
|
||||
|
||||
|
@ -632,6 +643,45 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);
|
|||
#endif
|
||||
#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
Implementation of Windows rwlock.
|
||||
|
||||
We use native (slim) rwlocks on Win7 and later, and fallback to portable
|
||||
implementation on earlier Windows.
|
||||
|
||||
slim rwlock are also available on Vista/WS2008, but we do not use it
|
||||
("trylock" APIs are missing on Vista)
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
/* Native rwlock (is_srwlock == TRUE) */
|
||||
struct
|
||||
{
|
||||
SRWLOCK srwlock; /* native reader writer lock */
|
||||
BOOL have_exclusive_srwlock; /* used for unlock */
|
||||
};
|
||||
|
||||
/*
|
||||
Portable implementation (is_srwlock == FALSE)
|
||||
Fields are identical with Unix my_rw_lock_t fields.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
pthread_mutex_t lock; /* lock for structure */
|
||||
pthread_cond_t readers; /* waiting readers */
|
||||
pthread_cond_t writers; /* waiting writers */
|
||||
int state; /* -1:writer,0:free,>0:readers */
|
||||
int waiters; /* number of waiting writers */
|
||||
#ifdef SAFE_MUTEX
|
||||
pthread_t write_thread;
|
||||
#endif
|
||||
};
|
||||
} my_rw_lock_t;
|
||||
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
/* Use our own version of read/write locks */
|
||||
typedef struct _my_rw_lock_t {
|
||||
pthread_mutex_t lock; /* lock for structure */
|
||||
|
@ -641,6 +691,8 @@ typedef struct _my_rw_lock_t {
|
|||
int waiters; /* number of waiting writers */
|
||||
} my_rw_lock_t;
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#define rw_lock_t my_rw_lock_t
|
||||
#define rw_rdlock(A) my_rw_rdlock((A))
|
||||
#define rw_wrlock(A) my_rw_wrlock((A))
|
||||
|
|
|
@ -26,7 +26,108 @@
|
|||
#include <process.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
static DWORD get_milliseconds(const struct timespec *abstime)
|
||||
{
|
||||
long long millis;
|
||||
union ft64 now;
|
||||
|
||||
if (abstime == NULL)
|
||||
return INFINITE;
|
||||
|
||||
GetSystemTimeAsFileTime(&now.ft);
|
||||
|
||||
/*
|
||||
Calculate time left to abstime
|
||||
- subtract start time from current time(values are in 100ns units)
|
||||
- convert to millisec by dividing with 10000
|
||||
*/
|
||||
millis= (abstime->tv.i64 - now.i64) / 10000;
|
||||
|
||||
/* Don't allow the timeout to be negative */
|
||||
if (millis < 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
Make sure the calculated timeout does not exceed original timeout
|
||||
value which could cause "wait for ever" if system time changes
|
||||
*/
|
||||
if (millis > abstime->max_timeout_msec)
|
||||
millis= abstime->max_timeout_msec;
|
||||
|
||||
if (millis > UINT_MAX)
|
||||
millis= UINT_MAX;
|
||||
|
||||
return (DWORD)millis;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
|
@ -55,7 +156,8 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
|
||||
static int legacy_cond_destroy(pthread_cond_t *cond)
|
||||
{
|
||||
DeleteCriticalSection(&cond->lock_waiting);
|
||||
|
||||
|
@ -67,48 +169,13 @@ int pthread_cond_destroy(pthread_cond_t *cond)
|
|||
}
|
||||
|
||||
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
return pthread_cond_timedwait(cond,mutex,NULL);
|
||||
}
|
||||
|
||||
|
||||
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
struct timespec *abstime)
|
||||
{
|
||||
int result;
|
||||
long timeout;
|
||||
union ft64 now;
|
||||
|
||||
if( abstime != NULL )
|
||||
{
|
||||
GetSystemTimeAsFileTime(&now.ft);
|
||||
|
||||
/*
|
||||
Calculate time left to abstime
|
||||
- subtract start time from current time(values are in 100ns units)
|
||||
- convert to millisec by dividing with 10000
|
||||
*/
|
||||
timeout= (long)((abstime->tv.i64 - now.i64) / 10000);
|
||||
|
||||
/* Don't allow the timeout to be negative */
|
||||
if (timeout < 0)
|
||||
timeout= 0L;
|
||||
|
||||
/*
|
||||
Make sure the calucated timeout does not exceed original timeout
|
||||
value which could cause "wait for ever" if system time changes
|
||||
*/
|
||||
if (timeout > abstime->max_timeout_msec)
|
||||
timeout= abstime->max_timeout_msec;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No time specified; don't expire */
|
||||
timeout= INFINITE;
|
||||
}
|
||||
DWORD timeout;
|
||||
|
||||
timeout= get_milliseconds(abstime);
|
||||
/*
|
||||
Block access if previous broadcast hasn't finished.
|
||||
This is just for safety and should normally not
|
||||
|
@ -144,7 +211,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|||
return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
|
||||
}
|
||||
|
||||
int pthread_cond_signal(pthread_cond_t *cond)
|
||||
static int legacy_cond_signal(pthread_cond_t *cond)
|
||||
{
|
||||
EnterCriticalSection(&cond->lock_waiting);
|
||||
|
||||
|
@ -157,7 +224,7 @@ int pthread_cond_signal(pthread_cond_t *cond)
|
|||
}
|
||||
|
||||
|
||||
int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||
static int legacy_cond_broadcast(pthread_cond_t *cond)
|
||||
{
|
||||
EnterCriticalSection(&cond->lock_waiting);
|
||||
/*
|
||||
|
@ -179,6 +246,87 @@ int pthread_cond_broadcast(pthread_cond_t *cond)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
{
|
||||
if (have_native_conditions)
|
||||
return 0; /* no destroy function */
|
||||
else
|
||||
return legacy_cond_destroy(cond);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
return pthread_cond_timedwait(cond, mutex, NULL);
|
||||
}
|
||||
|
||||
|
||||
int pthread_attr_init(pthread_attr_t *connect_att)
|
||||
{
|
||||
connect_att->dwStackSize = 0;
|
||||
|
|
|
@ -156,8 +156,19 @@ int win_pthread_setspecific(void *a,void *b,uint length)
|
|||
int my_pthread_once(my_pthread_once_t *once_control,
|
||||
void (*init_routine)(void))
|
||||
{
|
||||
LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
|
||||
MY_PTHREAD_ONCE_INIT);
|
||||
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);
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case MY_PTHREAD_ONCE_INIT:
|
||||
|
|
|
@ -19,6 +19,119 @@
|
|||
#if defined(THREAD) && !defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && !defined(HAVE_RWLOCK_INIT)
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL have_srwlock= FALSE;
|
||||
/* Prototypes and function pointers for windows functions */
|
||||
typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock);
|
||||
typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock);
|
||||
|
||||
static srw_func my_InitializeSRWLock;
|
||||
static srw_func my_AcquireSRWLockExclusive;
|
||||
static srw_func my_ReleaseSRWLockExclusive;
|
||||
static srw_func my_AcquireSRWLockShared;
|
||||
static srw_func my_ReleaseSRWLockShared;
|
||||
|
||||
static srw_bool_func my_TryAcquireSRWLockExclusive;
|
||||
static srw_bool_func my_TryAcquireSRWLockShared;
|
||||
|
||||
/**
|
||||
Check for presence of Windows slim reader writer lock function.
|
||||
Load function pointers.
|
||||
*/
|
||||
|
||||
static void check_srwlock_availability(void)
|
||||
{
|
||||
HMODULE module= GetModuleHandle("kernel32");
|
||||
|
||||
my_InitializeSRWLock= (srw_func) GetProcAddress(module,
|
||||
"InitializeSRWLock");
|
||||
my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module,
|
||||
"AcquireSRWLockExclusive");
|
||||
my_AcquireSRWLockShared= (srw_func) GetProcAddress(module,
|
||||
"AcquireSRWLockShared");
|
||||
my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module,
|
||||
"ReleaseSRWLockExclusive");
|
||||
my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module,
|
||||
"ReleaseSRWLockShared");
|
||||
my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module,
|
||||
"TryAcquireSRWLockExclusive");
|
||||
my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module,
|
||||
"TryAcquireSRWLockShared");
|
||||
|
||||
/*
|
||||
We currently require TryAcquireSRWLockExclusive. This API is missing on
|
||||
Vista, this means SRWLock are only used starting with Win7.
|
||||
|
||||
If "trylock" usage for rwlocks is eliminated from server codebase (it is used
|
||||
in a single place currently, in query cache), then SRWLock can be enabled on
|
||||
Vista too. In this case condition below needs to be changed to e.g check
|
||||
for my_InitializeSRWLock.
|
||||
*/
|
||||
|
||||
if (my_TryAcquireSRWLockExclusive)
|
||||
have_srwlock= TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int srw_init(my_rw_lock_t *rwp)
|
||||
{
|
||||
my_InitializeSRWLock(&rwp->srwlock);
|
||||
rwp->have_exclusive_srwlock = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srw_rdlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
my_AcquireSRWLockShared(&rwp->srwlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srw_tryrdlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
|
||||
if (!my_TryAcquireSRWLockShared(&rwp->srwlock))
|
||||
return EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srw_wrlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
my_AcquireSRWLockExclusive(&rwp->srwlock);
|
||||
rwp->have_exclusive_srwlock= TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srw_trywrlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock))
|
||||
return EBUSY;
|
||||
rwp->have_exclusive_srwlock= TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srw_unlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
if (rwp->have_exclusive_srwlock)
|
||||
{
|
||||
rwp->have_exclusive_srwlock= FALSE;
|
||||
my_ReleaseSRWLockExclusive(&rwp->srwlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_ReleaseSRWLockShared(&rwp->srwlock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*_WIN32 */
|
||||
|
||||
/*
|
||||
Source base from Sun Microsystems SPILT, simplified for MySQL use
|
||||
-- Joshua Chamas
|
||||
|
@ -62,6 +175,22 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused)))
|
|||
{
|
||||
pthread_condattr_t cond_attr;
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
Once initialization is used here rather than in my_init(), in order to
|
||||
- avoid my_init() pitfalls- (undefined order in which initialization should
|
||||
run)
|
||||
- be potentially useful C++ (static constructors)
|
||||
- just to simplify the API.
|
||||
Also, the overhead is of my_pthread_once is very small.
|
||||
*/
|
||||
static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT;
|
||||
my_pthread_once(&once_control, check_srwlock_availability);
|
||||
|
||||
if (have_srwlock)
|
||||
return srw_init(rwp);
|
||||
#endif
|
||||
|
||||
pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_condattr_init( &cond_attr );
|
||||
pthread_cond_init( &rwp->readers, &cond_attr );
|
||||
|
@ -77,6 +206,10 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused)))
|
|||
|
||||
int my_rwlock_destroy(rw_lock_t *rwp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return 0; /* no destroy function */
|
||||
#endif
|
||||
pthread_mutex_destroy( &rwp->lock );
|
||||
pthread_cond_destroy( &rwp->readers );
|
||||
pthread_cond_destroy( &rwp->writers );
|
||||
|
@ -86,6 +219,11 @@ int my_rwlock_destroy(rw_lock_t *rwp)
|
|||
|
||||
int my_rw_rdlock(rw_lock_t *rwp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return srw_rdlock(rwp);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
|
||||
/* active or queued writers */
|
||||
|
@ -100,6 +238,12 @@ int my_rw_rdlock(rw_lock_t *rwp)
|
|||
int my_rw_tryrdlock(rw_lock_t *rwp)
|
||||
{
|
||||
int res;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return srw_tryrdlock(rwp);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
if ((rwp->state < 0 ) || rwp->waiters)
|
||||
res= EBUSY; /* Can't get lock */
|
||||
|
@ -115,6 +259,11 @@ int my_rw_tryrdlock(rw_lock_t *rwp)
|
|||
|
||||
int my_rw_wrlock(rw_lock_t *rwp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return srw_wrlock(rwp);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
rwp->waiters++; /* another writer queued */
|
||||
|
||||
|
@ -130,6 +279,12 @@ int my_rw_wrlock(rw_lock_t *rwp)
|
|||
int my_rw_trywrlock(rw_lock_t *rwp)
|
||||
{
|
||||
int res;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return srw_trywrlock(rwp);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
if (rwp->state)
|
||||
res= EBUSY; /* Can't get lock */
|
||||
|
@ -145,6 +300,11 @@ int my_rw_trywrlock(rw_lock_t *rwp)
|
|||
|
||||
int my_rw_unlock(rw_lock_t *rwp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (have_srwlock)
|
||||
return srw_unlock(rwp);
|
||||
#endif
|
||||
|
||||
DBUG_PRINT("rw_unlock",
|
||||
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
|
|
|
@ -1172,7 +1172,29 @@ innobase_mysql_tmpfile(void)
|
|||
will be passed to fdopen(), it will be closed by invoking
|
||||
fclose(), which in turn will invoke close() instead of
|
||||
my_close(). */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Note that on Windows, the integer returned by mysql_tmpfile
|
||||
has no relation to C runtime file descriptor. Here, we need
|
||||
to call my_get_osfhandle to get the HANDLE and then convert it
|
||||
to C runtime filedescriptor. */
|
||||
{
|
||||
HANDLE hFile = my_get_osfhandle(fd);
|
||||
HANDLE hDup;
|
||||
BOOL bOK =
|
||||
DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
|
||||
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
if(bOK) {
|
||||
fd2 = _open_osfhandle((intptr_t)hDup,0);
|
||||
}
|
||||
else {
|
||||
my_osmaperr(GetLastError());
|
||||
fd2 = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd2 = dup(fd);
|
||||
#endif
|
||||
if (fd2 < 0) {
|
||||
DBUG_PRINT("error",("Got error %d on dup",fd2));
|
||||
my_errno=errno;
|
||||
|
|
|
@ -396,48 +396,7 @@ xtPublic int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
|
|||
|
||||
xtPublic int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)
|
||||
{
|
||||
pthread_mutex_t *mutex = &mt->mt_cs;
|
||||
int result;
|
||||
long timeout;
|
||||
union ft64 now;
|
||||
|
||||
if (abstime != NULL) {
|
||||
GetSystemTimeAsFileTime(&now.ft);
|
||||
|
||||
timeout = (long)((abstime->tv.i64 - now.i64) / 10000);
|
||||
if (timeout < 0)
|
||||
timeout = 0L;
|
||||
if (timeout > abstime->max_timeout_msec)
|
||||
timeout = abstime->max_timeout_msec;
|
||||
}
|
||||
else
|
||||
timeout= INFINITE;
|
||||
|
||||
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) {
|
||||
/* The last waiter must reset the broadcast
|
||||
* state (whther there was a broadcast or not)!
|
||||
*/
|
||||
ResetEvent(cond->events[xt_cond_type::BROADCAST]);
|
||||
SetEvent(cond->broadcast_block_event);
|
||||
}
|
||||
LeaveCriticalSection(&cond->lock_waiting);
|
||||
|
||||
EnterCriticalSection(mutex);
|
||||
|
||||
return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
|
||||
return pthread_cond_timedwait(cond, &(mt->mt_cs), abstime);
|
||||
}
|
||||
|
||||
xtPublic int xt_p_join(pthread_t thread, void **value)
|
||||
|
|
Loading…
Reference in a new issue