mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-19773 : simplify implementation of Windows rwlock
No need to do dynamic loading and fallbacks anymore. We can safely assume Windows 7, and availability of all SRWLock functions.
This commit is contained in:
@@ -581,36 +581,13 @@ extern int rw_pr_destroy(rw_pr_lock_t *);
|
|||||||
/**
|
/**
|
||||||
Implementation of Windows rwlock.
|
Implementation of Windows rwlock.
|
||||||
|
|
||||||
We use native (slim) rwlocks on Win7 and later, and fallback to portable
|
We use native (slim) rwlocks on Windows, which requires Win7
|
||||||
implementation on earlier Windows.
|
or later.
|
||||||
|
|
||||||
slim rwlock are also available on Vista/WS2008, but we do not use it
|
|
||||||
("trylock" APIs are missing on Vista)
|
|
||||||
*/
|
*/
|
||||||
typedef union
|
typedef struct _my_rwlock_t
|
||||||
{
|
|
||||||
/* Native rwlock (is_srwlock == TRUE) */
|
|
||||||
struct
|
|
||||||
{
|
{
|
||||||
SRWLOCK srwlock; /* native reader writer lock */
|
SRWLOCK srwlock; /* native reader writer lock */
|
||||||
BOOL have_exclusive_srwlock; /* used for unlock */
|
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;
|
} my_rw_lock_t;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -21,116 +21,66 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
static BOOL have_srwlock= FALSE;
|
int my_rw_init(my_rw_lock_t *rwp)
|
||||||
/* Prototypes and function pointers for windows functions */
|
|
||||||
typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock);
|
|
||||||
typedef BOOLEAN (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");
|
InitializeSRWLock(&rwp->srwlock);
|
||||||
|
|
||||||
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;
|
rwp->have_exclusive_srwlock = FALSE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int srw_rdlock(my_rw_lock_t *rwp)
|
int my_rw_rdlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
my_AcquireSRWLockShared(&rwp->srwlock);
|
AcquireSRWLockShared(&rwp->srwlock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int srw_tryrdlock(my_rw_lock_t *rwp)
|
int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
|
if (!TryAcquireSRWLockShared(&rwp->srwlock))
|
||||||
if (!my_TryAcquireSRWLockShared(&rwp->srwlock))
|
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int srw_wrlock(my_rw_lock_t *rwp)
|
int my_rw_wrlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
my_AcquireSRWLockExclusive(&rwp->srwlock);
|
AcquireSRWLockExclusive(&rwp->srwlock);
|
||||||
rwp->have_exclusive_srwlock= TRUE;
|
rwp->have_exclusive_srwlock= TRUE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int my_rw_trywrlock(my_rw_lock_t *rwp)
|
||||||
static int srw_trywrlock(my_rw_lock_t *rwp)
|
|
||||||
{
|
{
|
||||||
if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock))
|
if (!TryAcquireSRWLockExclusive(&rwp->srwlock))
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
rwp->have_exclusive_srwlock= TRUE;
|
rwp->have_exclusive_srwlock= TRUE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int srw_unlock(my_rw_lock_t *rwp)
|
int my_rw_unlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
if (rwp->have_exclusive_srwlock)
|
if (rwp->have_exclusive_srwlock)
|
||||||
{
|
{
|
||||||
rwp->have_exclusive_srwlock= FALSE;
|
rwp->have_exclusive_srwlock= FALSE;
|
||||||
my_ReleaseSRWLockExclusive(&rwp->srwlock);
|
ReleaseSRWLockExclusive(&rwp->srwlock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
my_ReleaseSRWLockShared(&rwp->srwlock);
|
ReleaseSRWLockShared(&rwp->srwlock);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*_WIN32 */
|
int my_rw_destroy(my_rw_lock_t* rwp)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!rwp->have_exclusive_srwlock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Source base from Sun Microsystems SPILT, simplified for MySQL use
|
Source base from Sun Microsystems SPILT, simplified for MySQL use
|
||||||
@@ -175,22 +125,6 @@ int my_rw_init(my_rw_lock_t *rwp)
|
|||||||
{
|
{
|
||||||
pthread_condattr_t cond_attr;
|
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_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST);
|
||||||
pthread_condattr_init( &cond_attr );
|
pthread_condattr_init( &cond_attr );
|
||||||
pthread_cond_init( &rwp->readers, &cond_attr );
|
pthread_cond_init( &rwp->readers, &cond_attr );
|
||||||
@@ -209,10 +143,6 @@ int my_rw_init(my_rw_lock_t *rwp)
|
|||||||
|
|
||||||
int my_rw_destroy(my_rw_lock_t *rwp)
|
int my_rw_destroy(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return 0; /* no destroy function */
|
|
||||||
#endif
|
|
||||||
DBUG_ASSERT(rwp->state == 0);
|
DBUG_ASSERT(rwp->state == 0);
|
||||||
pthread_mutex_destroy( &rwp->lock );
|
pthread_mutex_destroy( &rwp->lock );
|
||||||
pthread_cond_destroy( &rwp->readers );
|
pthread_cond_destroy( &rwp->readers );
|
||||||
@@ -223,11 +153,6 @@ int my_rw_destroy(my_rw_lock_t *rwp)
|
|||||||
|
|
||||||
int my_rw_rdlock(my_rw_lock_t *rwp)
|
int my_rw_rdlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return srw_rdlock(rwp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
|
|
||||||
/* active or queued writers */
|
/* active or queued writers */
|
||||||
@@ -242,12 +167,6 @@ int my_rw_rdlock(my_rw_lock_t *rwp)
|
|||||||
int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return srw_tryrdlock(rwp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
if ((rwp->state < 0 ) || rwp->waiters)
|
if ((rwp->state < 0 ) || rwp->waiters)
|
||||||
res= EBUSY; /* Can't get lock */
|
res= EBUSY; /* Can't get lock */
|
||||||
@@ -263,11 +182,6 @@ int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
|||||||
|
|
||||||
int my_rw_wrlock(my_rw_lock_t *rwp)
|
int my_rw_wrlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return srw_wrlock(rwp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
rwp->waiters++; /* another writer queued */
|
rwp->waiters++; /* another writer queued */
|
||||||
|
|
||||||
@@ -289,11 +203,6 @@ int my_rw_trywrlock(my_rw_lock_t *rwp)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return srw_trywrlock(rwp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
if (rwp->state)
|
if (rwp->state)
|
||||||
res= EBUSY; /* Can't get lock */
|
res= EBUSY; /* Can't get lock */
|
||||||
@@ -312,11 +221,6 @@ int my_rw_trywrlock(my_rw_lock_t *rwp)
|
|||||||
|
|
||||||
int my_rw_unlock(my_rw_lock_t *rwp)
|
int my_rw_unlock(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (have_srwlock)
|
|
||||||
return srw_unlock(rwp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DBUG_PRINT("rw_unlock",
|
DBUG_PRINT("rw_unlock",
|
||||||
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
@@ -347,7 +251,8 @@ int my_rw_unlock(my_rw_lock_t *rwp)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(NEED_MY_RW_LOCK) */
|
#endif /* !defined _WIN32 */
|
||||||
|
#endif /* NEED_MY_RW_LOCK*/
|
||||||
|
|
||||||
|
|
||||||
int rw_pr_init(rw_pr_lock_t *rwlock)
|
int rw_pr_init(rw_pr_lock_t *rwlock)
|
||||||
|
Reference in New Issue
Block a user