mirror of https://github.com/Icinga/icinga2.git
parent
684ad2641a
commit
187d443447
|
@ -205,7 +205,8 @@ CMAKE_OPTS="$CMAKE_OPTS -DBOOST_LIBRARYDIR=/usr/lib/boost141 \
|
|||
%if "%{_vendor}" != "suse"
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DICINGA2_PLUGINDIR=%{_libdir}/nagios/plugins"
|
||||
%else
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DICINGA2_PLUGINDIR=%{_prefix}/lib/nagios/plugins"
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DICINGA2_PLUGINDIR=%{_prefix}/lib/nagios/plugins \
|
||||
-DCMAKE_C_FLAGS='-march=i686' -DCMAKE_CXX_FLAGS='-march=i686'"
|
||||
%endif
|
||||
|
||||
%if 0%{?use_systemd}
|
||||
|
|
|
@ -30,7 +30,7 @@ set(base_SOURCES
|
|||
ringbuffer.cpp scriptfunction.cpp scriptfunctionwrapper.cpp
|
||||
scriptutils.cpp scriptvariable.cpp serializer.cpp socket.cpp stacktrace.cpp
|
||||
statsfunction.cpp stdiostream.cpp stream.cpp streamlogger.cpp streamlogger.thpp string.cpp
|
||||
sysloglogger.cpp sysloglogger.thpp tcpsocket.cpp threadpool.cpp timer.cpp
|
||||
sysloglogger.cpp sysloglogger.thpp tcpsocket.cpp thinmutex.cpp threadpool.cpp timer.cpp
|
||||
tlsstream.cpp tlsutility.cpp type.cpp unixsocket.cpp utility.cpp value.cpp
|
||||
value-operators.cpp workqueue.cpp
|
||||
)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "base/i2-base.hpp"
|
||||
#include "base/debug.hpp"
|
||||
#include "base/thinmutex.hpp"
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#ifndef _DEBUG
|
||||
|
@ -179,18 +180,14 @@ private:
|
|||
Object(const Object& other);
|
||||
Object& operator=(const Object& rhs);
|
||||
|
||||
#ifndef _DEBUG
|
||||
typedef boost::mutex MutexType;
|
||||
#else /* _DEBUG */
|
||||
typedef boost::recursive_mutex MutexType;
|
||||
mutable ThinMutex m_Mutex;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static boost::mutex m_DebugMutex;
|
||||
mutable bool m_Locked;
|
||||
mutable boost::thread::id m_LockOwner;
|
||||
#endif /* _DEBUG */
|
||||
|
||||
mutable MutexType m_Mutex;
|
||||
|
||||
friend struct ObjectLock;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
using namespace icinga;
|
||||
|
||||
ObjectLock::ObjectLock(void)
|
||||
: m_Object(NULL), m_Lock()
|
||||
: m_Object(NULL), m_Locked(false)
|
||||
{ }
|
||||
|
||||
ObjectLock::~ObjectLock(void)
|
||||
|
@ -32,14 +32,14 @@ ObjectLock::~ObjectLock(void)
|
|||
}
|
||||
|
||||
ObjectLock::ObjectLock(const Object::Ptr& object)
|
||||
: m_Object(object.get()), m_Lock()
|
||||
: m_Object(object.get()), m_Locked(false)
|
||||
{
|
||||
if (m_Object)
|
||||
Lock();
|
||||
}
|
||||
|
||||
ObjectLock::ObjectLock(const Object *object)
|
||||
: m_Object(object), m_Lock()
|
||||
: m_Object(object), m_Locked(false)
|
||||
{
|
||||
if (m_Object)
|
||||
Lock();
|
||||
|
@ -47,10 +47,11 @@ ObjectLock::ObjectLock(const Object *object)
|
|||
|
||||
void ObjectLock::Lock(void)
|
||||
{
|
||||
ASSERT(!m_Lock.owns_lock() && m_Object != NULL);
|
||||
ASSERT(!m_Locked && m_Object != NULL);
|
||||
ASSERT(!m_Object->OwnsLock());
|
||||
|
||||
m_Lock = Object::MutexType::scoped_lock(m_Object->m_Mutex);
|
||||
m_Object->m_Mutex.Lock();
|
||||
m_Locked = true;
|
||||
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
|
@ -66,11 +67,13 @@ void ObjectLock::Unlock(void)
|
|||
#ifdef _DEBUG
|
||||
{
|
||||
boost::mutex::scoped_lock lock(Object::m_DebugMutex);
|
||||
|
||||
if (m_Lock.owns_lock())
|
||||
if (m_Locked)
|
||||
m_Object->m_Locked = false;
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
|
||||
m_Lock = Object::MutexType::scoped_lock();
|
||||
if (m_Locked) {
|
||||
m_Object->m_Mutex.Unlock();
|
||||
m_Locked = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
private:
|
||||
const Object *m_Object;
|
||||
Object::MutexType::scoped_lock m_Lock;
|
||||
bool m_Locked;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
|
||||
* *
|
||||
* 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; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* 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 St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "base/thinmutex.hpp"
|
||||
#include "base/initialize.hpp"
|
||||
#include "base/timer.hpp"
|
||||
#include "base/convert.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
#ifdef _DEBUG
|
||||
uintptr_t ThinMutex::m_TotalMutexes;
|
||||
uintptr_t ThinMutex::m_InflatedMutexes;
|
||||
uintptr_t ThinMutex::m_DeadMutexes;
|
||||
|
||||
static Timer::Ptr l_Timer;
|
||||
|
||||
void ThinMutex::DebugTimerHandler(void)
|
||||
{
|
||||
Log(LogNotice, "ThinMutex")
|
||||
<< "Mutexes: " << ThinMutex::m_TotalMutexes - ThinMutex::m_DeadMutexes
|
||||
<< ", Inflated Mutexes: " << ThinMutex::m_InflatedMutexes
|
||||
<< ", Dead Mutexes: " << ThinMutex::m_DeadMutexes;
|
||||
}
|
||||
|
||||
static void InitThinMutex(void)
|
||||
{
|
||||
l_Timer = make_shared<Timer>();
|
||||
l_Timer->SetInterval(10);
|
||||
l_Timer->OnTimerExpired.connect(boost::bind(&ThinMutex::DebugTimerHandler));
|
||||
l_Timer->Start();
|
||||
}
|
||||
|
||||
INITIALIZE_ONCE(&InitThinMutex);
|
||||
#endif /* _DEBUG */
|
||||
|
||||
void ThinMutex::MakeNative(void)
|
||||
{
|
||||
boost::mutex *mtx = new boost::mutex();
|
||||
mtx->lock();
|
||||
#ifdef _WIN32
|
||||
# ifdef _WIN64
|
||||
InterlockedCompareExchange64(&m_Data, reinterpret_cast<LONGLONG>(mtx), THINLOCK_LOCKED);
|
||||
# else /* _WIN64 */
|
||||
InterlockedCompareExchange(&m_Data, reinterpret_cast<LONG>(mtx), THINLOCK_LOCKED);
|
||||
# endif /* _WIN64 */
|
||||
#else /* _WIN32 */
|
||||
__sync_bool_compare_and_swap(&m_Data, THINLOCK_LOCKED, reinterpret_cast<uintptr_t>(mtx));
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifdef _WIN32
|
||||
InterlockedIncrement(&m_InflatedMutexes);
|
||||
# else /* _WIN32 */
|
||||
__sync_fetch_and_add(&m_InflatedMutexes, 1);
|
||||
# endif /* _WIN32 */
|
||||
#endif /* _DEBUG */
|
||||
}
|
||||
|
||||
void ThinMutex::DestroyNative(void)
|
||||
{
|
||||
delete reinterpret_cast<boost::mutex *>(m_Data);
|
||||
}
|
||||
|
||||
void ThinMutex::LockNative(void)
|
||||
{
|
||||
boost::mutex *mtx = reinterpret_cast<boost::mutex *>(m_Data);
|
||||
mtx->lock();
|
||||
}
|
||||
|
||||
void ThinMutex::UnlockNative(void)
|
||||
{
|
||||
boost::mutex *mtx = reinterpret_cast<boost::mutex *>(m_Data);
|
||||
mtx->unlock();
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
|
||||
* *
|
||||
* 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; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* 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 St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef THINMUTEX_H
|
||||
#define THINMUTEX_H
|
||||
|
||||
#include "base/i2-base.hpp"
|
||||
#ifndef _WIN32
|
||||
#include <sched.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310 && (defined(_M_IX86) || defined(_M_X64))
|
||||
extern "C" void _mm_pause();
|
||||
#pragma intrinsic(_mm_pause)
|
||||
#define SPIN_PAUSE() _mm_pause()
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define SPIN_PAUSE() __asm__ __volatile__("rep; nop" : : : "memory")
|
||||
#endif
|
||||
|
||||
#define THINLOCK_UNLOCKED 0
|
||||
#define THINLOCK_LOCKED 1
|
||||
|
||||
namespace icinga {
|
||||
|
||||
class I2_BASE_API ThinMutex
|
||||
{
|
||||
public:
|
||||
inline ThinMutex(void)
|
||||
: m_Data(THINLOCK_UNLOCKED)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
# ifdef _WIN32
|
||||
InterlockedIncrement(&m_TotalMutexes);
|
||||
# else /* _WIN32 */
|
||||
__sync_fetch_and_add(&m_TotalMutexes, 1);
|
||||
# endif /* _WIN32 */
|
||||
#endif /* _DEBUG */
|
||||
}
|
||||
|
||||
inline ~ThinMutex(void)
|
||||
{
|
||||
if (m_Data > THINLOCK_LOCKED)
|
||||
DestroyNative();
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifdef _WIN32
|
||||
InterlockedDecrement(&m_TotalMutexes);
|
||||
# else /* _WIN32 */
|
||||
__sync_fetch_and_add(&m_DeadMutexes, 1);
|
||||
# endif /* _WIN32 */
|
||||
#endif /* _DEBUG */
|
||||
}
|
||||
|
||||
inline void Spin(unsigned int it)
|
||||
{
|
||||
if (it < 8) {
|
||||
/* Do nothing. */
|
||||
}
|
||||
#ifdef SPIN_PAUSE
|
||||
else if (it < 16) {
|
||||
SPIN_PAUSE();
|
||||
}
|
||||
#endif /* SPIN_PAUSE */
|
||||
else {
|
||||
#ifdef _WIN32
|
||||
Sleep(0);
|
||||
#else /* _WIN32 */
|
||||
sched_yield();
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
}
|
||||
|
||||
inline void Lock(void)
|
||||
{
|
||||
bool contended = false;
|
||||
unsigned int it = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef _WIN64
|
||||
while (InterlockedCompareExchange64(&m_Data, THINLOCK_LOCKED, THINLOCK_UNLOCKED) != THINLOCK_UNLOCKED) {
|
||||
# else /* _WIN64 */
|
||||
while (InterlockedCompareExchange(&m_Data, THINLOCK_LOCKED, THINLOCK_UNLOCKED) != THINLOCK_UNLOCKED) {
|
||||
# endif /* _WIN64 */
|
||||
#else /* _WIN32 */
|
||||
while (!__sync_bool_compare_and_swap(&m_Data, THINLOCK_UNLOCKED, THINLOCK_LOCKED)) {
|
||||
#endif /* _WIN32 */
|
||||
if (m_Data > THINLOCK_LOCKED) {
|
||||
LockNative();
|
||||
return;
|
||||
}
|
||||
|
||||
contended = true;
|
||||
|
||||
Spin(it);
|
||||
it++;
|
||||
}
|
||||
|
||||
if (contended)
|
||||
MakeNative();
|
||||
}
|
||||
|
||||
void MakeNative(void);
|
||||
void DestroyNative(void);
|
||||
|
||||
void LockNative(void);
|
||||
void UnlockNative(void);
|
||||
|
||||
inline void Unlock(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
# ifdef _WIN64
|
||||
if (InterlockedCompareExchange64(&m_Data, THINLOCK_UNLOCKED, THINLOCK_LOCKED) != THINLOCK_LOCKED)
|
||||
# else /* _WIN64 */
|
||||
if (InterlockedCompareExchange(&m_Data, THINLOCK_UNLOCKED, THINLOCK_LOCKED) != THINLOCK_LOCKED)
|
||||
# endif /* _WIN64 */
|
||||
#else /* _WIN32 */
|
||||
if (!__sync_bool_compare_and_swap(&m_Data, THINLOCK_LOCKED, THINLOCK_UNLOCKED))
|
||||
#endif /* _WIN32 */
|
||||
UnlockNative();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
static void DebugTimerHandler(void);
|
||||
#endif /* _DEBUG */
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
# ifdef _WIN64
|
||||
LONGLONG m_Data;
|
||||
# else /* _WIN64 */
|
||||
LONG m_Data;
|
||||
# endif /* _WIN64 */
|
||||
#else /* _WIN32 */
|
||||
uintptr_t m_Data;
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _DEBUG
|
||||
static uintptr_t m_TotalMutexes;
|
||||
static uintptr_t m_InflatedMutexes;
|
||||
static uintptr_t m_DeadMutexes;
|
||||
#endif /* _DEBUG */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* THINMUTEX_H */
|
Loading…
Reference in New Issue