2016-08-12 11:17:45 +03:00
|
|
|
/*****************************************************************************
|
|
|
|
|
|
|
|
Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
2017-01-30 17:00:51 +02:00
|
|
|
Copyright (c) 2017, MariaDB Corporation.
|
2016-08-12 11:17:45 +03:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; version 2 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/******************************************************************//**
|
|
|
|
@file include/ut0mutex.h
|
|
|
|
Policy based mutexes.
|
|
|
|
|
|
|
|
Created 2012-03-24 Sunny Bains.
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
#ifndef UNIV_INNOCHECKSUM
|
|
|
|
|
|
|
|
#ifndef ut0mutex_h
|
|
|
|
#define ut0mutex_h
|
|
|
|
|
2017-01-07 15:36:08 +02:00
|
|
|
extern uint srv_spin_wait_delay;
|
2016-08-12 11:17:45 +03:00
|
|
|
extern ulong srv_n_spin_wait_rounds;
|
|
|
|
|
|
|
|
#include "sync0policy.h"
|
|
|
|
#include "ib0mutex.h"
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
/** Create a typedef using the MutexType<PolicyType>
|
|
|
|
@param[in] M Mutex type
|
|
|
|
@param[in[ P Policy type
|
|
|
|
@param[in] T The resulting typedef alias */
|
|
|
|
#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
|
|
|
|
|
|
|
|
typedef OSMutex EventMutex;
|
|
|
|
|
|
|
|
# ifdef HAVE_IB_LINUX_FUTEX
|
|
|
|
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
|
|
|
|
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
|
|
|
|
# endif /* HAVE_IB_LINUX_FUTEX */
|
|
|
|
|
|
|
|
UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
|
|
|
|
UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex);
|
|
|
|
|
|
|
|
UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
|
|
|
|
UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex);
|
|
|
|
|
|
|
|
UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
|
|
|
|
UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
|
|
|
|
|
|
|
|
#ifdef MUTEX_FUTEX
|
|
|
|
/** The default mutex type. */
|
|
|
|
typedef FutexMutex ib_mutex_t;
|
|
|
|
typedef BlockFutexMutex ib_bpmutex_t;
|
|
|
|
#define MUTEX_TYPE "Uses futexes"
|
|
|
|
#elif defined(MUTEX_SYS)
|
|
|
|
typedef SysMutex ib_mutex_t;
|
|
|
|
typedef BlockSysMutex ib_bpmutex_t;
|
|
|
|
#define MUTEX_TYPE "Uses system mutexes"
|
|
|
|
#elif defined(MUTEX_EVENT)
|
|
|
|
typedef SyncArrayMutex ib_mutex_t;
|
|
|
|
typedef BlockSyncArrayMutex ib_bpmutex_t;
|
|
|
|
#define MUTEX_TYPE "Uses event mutexes"
|
|
|
|
#else
|
|
|
|
#error "ib_mutex_t type is unknown"
|
|
|
|
#endif /* MUTEX_FUTEX */
|
|
|
|
|
2017-01-07 15:36:08 +02:00
|
|
|
extern uint srv_spin_wait_delay;
|
2016-08-12 11:17:45 +03:00
|
|
|
extern ulong srv_n_spin_wait_rounds;
|
|
|
|
|
2017-03-01 08:27:39 +02:00
|
|
|
#define mutex_create(I, M) mutex_init((M), (I), \
|
|
|
|
__FILE__, __LINE__)
|
2016-08-12 11:17:45 +03:00
|
|
|
|
2017-03-01 08:27:39 +02:00
|
|
|
#define mutex_enter_loc(M,file,line) (M)->enter( \
|
|
|
|
uint32_t(srv_n_spin_wait_rounds), \
|
|
|
|
uint32_t(srv_spin_wait_delay), \
|
|
|
|
file, line)
|
|
|
|
#define mutex_enter(M) mutex_enter_loc(M, __FILE__, __LINE__)
|
2016-08-12 11:17:45 +03:00
|
|
|
|
|
|
|
#define mutex_enter_nospin(M) (M)->enter( \
|
|
|
|
0, \
|
|
|
|
0, \
|
2017-03-01 08:27:39 +02:00
|
|
|
__FILE__, uint32_t(__LINE__))
|
2016-08-12 11:17:45 +03:00
|
|
|
|
2017-03-01 08:27:39 +02:00
|
|
|
#define mutex_enter_nowait(M) (M)->trylock(__FILE__, \
|
|
|
|
uint32_t(__LINE__))
|
2016-08-12 11:17:45 +03:00
|
|
|
|
|
|
|
#define mutex_exit(M) (M)->exit()
|
|
|
|
|
|
|
|
#define mutex_free(M) mutex_destroy(M)
|
|
|
|
|
|
|
|
#ifdef UNIV_DEBUG
|
|
|
|
/**
|
|
|
|
Checks that the mutex has been initialized. */
|
|
|
|
#define mutex_validate(M) (M)->validate()
|
|
|
|
|
|
|
|
/**
|
|
|
|
Checks that the current thread owns the mutex. Works only
|
|
|
|
in the debug version. */
|
|
|
|
#define mutex_own(M) (M)->is_owned()
|
|
|
|
#else
|
|
|
|
#define mutex_own(M) /* No op */
|
|
|
|
#define mutex_validate(M) /* No op */
|
|
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
|
|
|
|
/** Iterate over the mutex meta data */
|
|
|
|
class MutexMonitor {
|
|
|
|
public:
|
|
|
|
/** Constructor */
|
|
|
|
MutexMonitor() { }
|
|
|
|
|
|
|
|
/** Destructor */
|
|
|
|
~MutexMonitor() { }
|
|
|
|
|
|
|
|
/** Enable the mutex monitoring */
|
|
|
|
void enable();
|
|
|
|
|
|
|
|
/** Disable the mutex monitoring */
|
|
|
|
void disable();
|
|
|
|
|
|
|
|
/** Reset the mutex monitoring values */
|
|
|
|
void reset();
|
|
|
|
|
|
|
|
/** Invoke the callback for each active mutex collection
|
|
|
|
@param[in,out] callback Functor to call
|
|
|
|
@return false if callback returned false */
|
|
|
|
template<typename Callback>
|
|
|
|
bool iterate(Callback& callback) const
|
|
|
|
UNIV_NOTHROW
|
|
|
|
{
|
|
|
|
LatchMetaData::iterator end = latch_meta.end();
|
|
|
|
|
|
|
|
for (LatchMetaData::iterator it = latch_meta.begin();
|
|
|
|
it != end;
|
|
|
|
++it) {
|
|
|
|
|
|
|
|
/* Some of the slots will be null in non-debug mode */
|
|
|
|
|
|
|
|
if (*it == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
latch_meta_t* latch_meta = *it;
|
|
|
|
|
|
|
|
bool ret = callback(*latch_meta);
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Defined in sync0sync.cc */
|
|
|
|
extern MutexMonitor* mutex_monitor;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Creates, or rather, initializes a mutex object in a specified memory
|
|
|
|
location (which must be appropriately aligned). The mutex is initialized
|
|
|
|
in the reset state. Explicit freeing of the mutex with mutex_free is
|
|
|
|
necessary only if the memory block containing it is freed.
|
|
|
|
Add the mutex instance to the global mutex list.
|
|
|
|
@param[in,out] mutex mutex to initialise
|
|
|
|
@param[in] id The mutex ID (Latch ID)
|
|
|
|
@param[in] filename Filename from where it was called
|
|
|
|
@param[in] line Line number in filename from where called */
|
|
|
|
template <typename Mutex>
|
|
|
|
void mutex_init(
|
|
|
|
Mutex* mutex,
|
|
|
|
latch_id_t id,
|
|
|
|
const char* file_name,
|
|
|
|
uint32_t line)
|
|
|
|
{
|
|
|
|
new(mutex) Mutex();
|
|
|
|
|
|
|
|
mutex->init(id, file_name, line);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Removes a mutex instance from the mutex list. The mutex is checked to
|
|
|
|
be in the reset state.
|
|
|
|
@param[in,out] mutex mutex instance to destroy */
|
|
|
|
template <typename Mutex>
|
|
|
|
void mutex_destroy(
|
|
|
|
Mutex* mutex)
|
|
|
|
{
|
|
|
|
mutex->destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ut0mutex_h */
|
|
|
|
|
|
|
|
#endif /* UNIV_INNOCHECKSUM */
|