From 501ef6dfedf6871dd2115b2ba3766be7f89c4062 Mon Sep 17 00:00:00 2001 From: Richard Chapman Date: Wed, 12 Jun 2024 11:10:09 +0100 Subject: [PATCH] HPCC-31981 Mutex code was inefficient Refactor Mutex class to use modern C++ standard mutexes, which are significantly faster. Leave old Mutex class in place just in case the unlockall functionality is significant in the one place that uses it. Also fixes Incorrect summary stats fromjlib timing test Signed-off-by: Richard Chapman --- deployment/deploy/DeployTask.cpp | 4 +- esp/esplib/pqueue.hpp | 279 ------------------ system/jlib/jlog.cpp | 2 +- system/jlib/jlog.ipp | 2 +- system/jlib/jmutex.cpp | 39 ++- system/jlib/jmutex.hpp | 98 ++++-- system/jlib/jpqueue.hpp | 27 +- system/mp/mpcomm.cpp | 8 +- .../security/LdapSecurity/ldapconnection.cpp | 2 +- system/security/LdapSecurity/ldapsecurity.cpp | 2 +- system/security/LdapSecurity/permissions.cpp | 4 +- testing/unittests/jlibtests.cpp | 16 +- 12 files changed, 129 insertions(+), 354 deletions(-) delete mode 100644 esp/esplib/pqueue.hpp diff --git a/deployment/deploy/DeployTask.cpp b/deployment/deploy/DeployTask.cpp index 841cab4edc3..754575486d5 100644 --- a/deployment/deploy/DeployTask.cpp +++ b/deployment/deploy/DeployTask.cpp @@ -752,7 +752,7 @@ class CDeployTask : public CInterface, implements IDeployTask // Prompt to retry on error m_errorString.appendf("Cannot copy %s to %s: ", source, target); - synchronized block(s_monitor); + MonitorBlock block(s_monitor); if (m_pCallback->getAbortStatus())//has some other thread set the global abort flag? break; //go back to beginning of loop where we exit on abort @@ -822,7 +822,7 @@ class CDeployTask : public CInterface, implements IDeployTask if (m_msgBoxOwner)//did this thread show the message box in last iteration of this loop? { - synchronized block(s_monitor); + MonitorBlock block(s_monitor); s_msgBoxActive = false; m_msgBoxOwner = false;//up for grabs by other threads s_monitor.notifyAll(); diff --git a/esp/esplib/pqueue.hpp b/esp/esplib/pqueue.hpp deleted file mode 100644 index 9b5f59e40a7..00000000000 --- a/esp/esplib/pqueue.hpp +++ /dev/null @@ -1,279 +0,0 @@ -/*############################################################################## - - HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -############################################################################## */ - -#ifndef __PQUEUE_HPP -#define __PQUEUE_HPP - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning(disable : 4284 ) // return type for '...::operator ->' is '...' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) -#endif - -#include "jlibplus.hpp" - -#include "jmutex.hpp" -#include "jthread.hpp" -#include "jmisc.hpp" -#include -#include - - -namespace esp -{ - -template class WaitQueue: public CInterface, protected Mutex, implements IInterface -{ -public: - IMPLEMENT_IINTERFACE; - WaitQueue(): counter(), stopped(false), waiting(0) - { - } - - ~WaitQueue() - { - stop(); - synchronized block(*this); - while(waiting) - { - counter.signal(waiting); // actually need only one and only once - wait(INFINITE); - } - } - - unsigned size() - { - synchronized block(*this); - return queue.size(); - } - - T get(unsigned timeout=INFINITE) - { - synchronized block(*this); - for(;;) - { - if(stopped) - return 0; - if(queue.size()) - break; - if(!wait(timeout)) - return 0; - } - T item=queue.front(); - queue.pop_front(); - return item; - } - - bool put(const T& item) - { - synchronized block(*this); - if(stopped) - return true; - queue.push_back(item); - counter.signal(); - return waiting>0; - } - - void stop() - { - synchronized block(*this); - stopped=true; - queue.clear(); - counter.signal(waiting); - } - - bool isStopped() - { - synchronized block(*this); - return stopped; - } - -private: - - bool wait(unsigned timeout) - { - bool ret=false; - waiting++; - - int locked = unlockAll(); - ret=counter.wait(timeout); - lockAll(locked); - - waiting--; - return ret; - } - - Semaphore counter; - std::list queue; - volatile unsigned waiting; - volatile bool stopped; //need event -}; - -interface ITask: extends IInterface -{ - virtual int run()=0; - virtual bool stop()=0; -}; - -interface IErrorListener: extends IInterface -{ - virtual void reportError(const char* err,...) __attribute__((format(printf, 2, 3))) =0; -}; - -class TaskQueue -{ -public: - TaskQueue(size32_t _maxsize,IErrorListener* _err=0): maxsize(_maxsize), err(_err) - { - } - - ~TaskQueue() - { - stop(); - join(); - } - - void put(ITask* task) - { - bool needthread=!queue.put(task); - if(needthread) - { - synchronized block(mworkers); - if(workers.size()start(); - } -// DBGLOG("%d threads",workers.size()); - } - } - - void stop() - { - queue.stop(); - - synchronized block(mworkers); - for(Workers::iterator it=workers.begin();it!=workers.end();it++) - (*it)->stop(); // no good if threads did not clean up - } - - void join() - { - synchronized block(mworkers); - while(!workers.empty()) - { - mworkers.wait(); - } - - } - - void setErrorListener(IErrorListener* _err) - { - err.set(_err); - } - - void reportError(const char* e) - { - if(err) - { - synchronized block(merr); - err->reportError(e); - } - } - -private: - - class WorkerThread: public Thread - { - public: - WorkerThread(TaskQueue& _tq): tq(_tq), stopped(false) - { - } - - virtual int run() - { - for(;;) - { - - try - { - task.setown(tq.queue.get(1000).get()); - if(stopped || !task) - break; - task->run(); - } - catch (IException *E) - { - StringBuffer err; - E->errorMessage(err); - tq.reportError(err.str()); - E->Release(); - } - catch (...) - { - tq.reportError("Unknown exception "); - } - task.clear(); - } - Release(); // There should be one more - return 0; - } - - - bool stop() - { - stopped=true; - Linked t(task.get()); - return t ? t->stop() : true; - } - - virtual void beforeDispose() - { - tq.remove(this); - } - - private: - TaskQueue& tq; - volatile bool stopped; - Owned task; - }; - - void remove(WorkerThread* th) - { - synchronized block(mworkers); - workers.remove(th); - if(workers.empty()) - mworkers.notifyAll(); - } - - - WaitQueue > queue; - - size32_t maxsize; - friend WorkerThread; - typedef std::list Workers; - Workers workers; - Monitor mworkers; - Linked err; - Mutex merr; -}; -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/system/jlib/jlog.cpp b/system/jlib/jlog.cpp index ba13f2b9276..af28ee6ccaa 100644 --- a/system/jlib/jlog.cpp +++ b/system/jlib/jlog.cpp @@ -1437,7 +1437,7 @@ bool CLogMsgManager::MsgProcessor::flush(unsigned timeout) return false; try { - synchronized block(pullCycleMutex, timeout+start-now); + TimedMutexBlock block(pullCycleMutex, timeout+start-now); } catch(IException * e) { diff --git a/system/jlib/jlog.ipp b/system/jlib/jlog.ipp index 31a6f05dfeb..7318156a0b1 100644 --- a/system/jlib/jlog.ipp +++ b/system/jlib/jlog.ipp @@ -722,7 +722,7 @@ private: CallbackInterThreadQueueOf q; unsigned droppingLimit; unsigned numToDrop = 1; - Mutex pullCycleMutex; + TimedMutex pullCycleMutex; }; Owned processor; diff --git a/system/jlib/jmutex.cpp b/system/jlib/jmutex.cpp index 8d1fe0b369a..f2b5589ac1c 100644 --- a/system/jlib/jmutex.cpp +++ b/system/jlib/jmutex.cpp @@ -27,7 +27,7 @@ //=========================================================================== #ifndef _WIN32 -Mutex::Mutex() +LegacyMutex::LegacyMutex() { pthread_mutex_init(&mutex, NULL); pthread_cond_init(&lock_free, NULL); @@ -35,13 +35,13 @@ Mutex::Mutex() lockcount = 0; } -Mutex::~Mutex() +LegacyMutex::~LegacyMutex() { pthread_cond_destroy(&lock_free); pthread_mutex_destroy(&mutex); } -void Mutex::lock() +void LegacyMutex::lock() { pthread_mutex_lock(&mutex); while ((owner!=0) && !pthread_equal(owner, pthread_self())) @@ -51,7 +51,7 @@ void Mutex::lock() pthread_mutex_unlock(&mutex); } -bool Mutex::lockWait(unsigned timeout) +bool LegacyMutex::lockWait(unsigned timeout) { if (timeout==(unsigned)-1) { lock(); @@ -76,7 +76,7 @@ bool Mutex::lockWait(unsigned timeout) return true; } -void Mutex::unlock() +void LegacyMutex::unlock() { pthread_mutex_lock(&mutex); #ifdef _DEBUG @@ -90,7 +90,7 @@ void Mutex::unlock() pthread_mutex_unlock(&mutex); } -void Mutex::lockAll(int count) +void LegacyMutex::lockAll(int count) { if (count) { pthread_mutex_lock(&mutex); @@ -102,7 +102,7 @@ void Mutex::lockAll(int count) } } -int Mutex::unlockAll() +int LegacyMutex::unlockAll() { pthread_mutex_lock(&mutex); int ret = lockcount; @@ -118,9 +118,6 @@ int Mutex::unlockAll() return ret; } - - - inline bool read_data(int fd, void *buf, size_t nbytes) { size32_t nread = 0; @@ -268,7 +265,17 @@ void NamedMutex::unlock() #endif -void synchronized::throwLockException(unsigned timeout) +bool TimedMutex::lockWait(unsigned timeout) +{ + if (timeout==(unsigned)-1) { + lock(); + return true; + } + std::chrono::milliseconds ms(timeout); + return mutex.try_lock_for(ms); +} + +void TimedMutexBlock::throwLockException(unsigned timeout) { throw MakeStringException(0,"Can not lock - %d",timeout); } @@ -279,14 +286,14 @@ void synchronized::throwLockException(unsigned timeout) void Monitor::wait() { - assertex(owner==GetCurrentThreadId()); + assertex(mutex.owner==GetCurrentThreadId()); waiting++; void *cur = last; last = &cur; while (1) { - int locked = unlockAll(); + int locked = mutex.unlockAll(); sem->wait(); - lockAll(locked); + mutex.lockAll(locked); if (cur==NULL) { // i.e. first in void **p=(void **)&last; while (*p!=&cur) @@ -300,7 +307,7 @@ void Monitor::wait() void Monitor::notify() { // should always be locked - assertex(owner==GetCurrentThreadId()); + assertex(mutex.owner==GetCurrentThreadId()); if (waiting) { waiting--; @@ -310,7 +317,7 @@ void Monitor::notify() void Monitor::notifyAll() { // should always be locked - assertex(owner==GetCurrentThreadId()); + assertex(mutex.owner==GetCurrentThreadId()); if (waiting) { sem->signal(waiting); diff --git a/system/jlib/jmutex.hpp b/system/jlib/jmutex.hpp index d9f072cf6ea..4e3f51cdc7f 100644 --- a/system/jlib/jmutex.hpp +++ b/system/jlib/jmutex.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include "jiface.hpp" #include "jsem.hpp" @@ -46,10 +47,11 @@ extern jlib_decl void spinUntilReady(std::atomic_uint &value); #endif #ifdef _WIN32 -class jlib_decl Mutex +class jlib_decl LegacyMutex { +friend class Monitor; protected: - Mutex(const char *name) + LegacyMutex(const char *name) { mutex = CreateMutex(NULL, FALSE, name); assertex(mutex); @@ -57,13 +59,13 @@ class jlib_decl Mutex owner = 0; } public: - Mutex() + LegacyMutex() { mutex = CreateMutex(NULL, FALSE, NULL); lockcount = 0; owner = 0; } - ~Mutex() + ~LegacyMutex() { if (owner != 0) printf("Warning - Owned mutex destroyed"); // can't use DBGLOG here! @@ -123,25 +125,14 @@ class jlib_decl Mutex int lockcount; }; -class jlib_decl NamedMutex: public Mutex -{ -public: - NamedMutex(const char *name) - : Mutex(name) - { - } -}; - - - #else // posix -class jlib_decl Mutex +class jlib_decl LegacyMutex { + friend class Monitor; public: - Mutex(); -// Mutex(const char *name); //not supported - ~Mutex(); + LegacyMutex(); + ~LegacyMutex(); void lock(); bool lockWait(unsigned timeout); void unlock(); @@ -154,7 +145,35 @@ class jlib_decl Mutex int lockcount; pthread_cond_t lock_free; }; +#endif + +class jlib_decl SimpleMutex +{ +public: + void lock() { mutex.lock(); }; + void unlock() { mutex.unlock(); }; +private: + std::mutex mutex; +}; + +class jlib_decl Mutex +{ +public: + void lock() { mutex.lock(); }; + void unlock() { mutex.unlock(); }; +private: + std::recursive_mutex mutex; +}; +class jlib_decl TimedMutex +{ +public: + void lock() { mutex.lock(); }; + bool lockWait(unsigned timeout); + void unlock() { mutex.unlock(); }; +private: + std::recursive_timed_mutex mutex; +}; class jlib_decl NamedMutex { @@ -165,23 +184,30 @@ class jlib_decl NamedMutex bool lockWait(unsigned timeout); void unlock(); private: - Mutex threadmutex; + TimedMutex threadmutex; char *mutexfname; }; +template class jlib_decl MutexBlock +{ +private: + T &mutex; +public: + MutexBlock(T &m) : mutex(m) { mutex.lock(); }; + ~MutexBlock() { mutex.unlock(); }; +}; +typedef MutexBlock synchronized; -#endif - -class jlib_decl synchronized +class jlib_decl TimedMutexBlock { private: - Mutex &mutex; + TimedMutex &mutex; void throwLockException(unsigned timeout); public: - synchronized(Mutex &m) : mutex(m) { mutex.lock(); }; - synchronized(Mutex &m,unsigned timeout) : mutex(m) { if(!mutex.lockWait(timeout)) throwLockException(timeout); } - inline ~synchronized() { mutex.unlock(); }; + TimedMutexBlock(TimedMutex &m) : mutex(m) { mutex.lock(); }; + TimedMutexBlock(TimedMutex &m, unsigned timeout) : mutex(m) { if(!mutex.lockWait(timeout)) throwLockException(timeout); } + inline ~TimedMutexBlock() { mutex.unlock(); }; }; #ifdef _WIN32 @@ -561,14 +587,16 @@ class NonReentrantSpinUnblock -class jlib_decl Monitor: public Mutex +class jlib_decl Monitor { // Like a java object - you can synchronize on it for a block, wait for a notify on it, or notify on it + friend class MonitorBlock; Semaphore *sem; int waiting; void *last; + LegacyMutex mutex; public: - Monitor() : Mutex() { sem = new Semaphore(); waiting = 0; last = NULL; } + Monitor() { sem = new Semaphore(); waiting = 0; last = NULL; } // Monitor(const char *name) : Mutex(name) { sem = new Semaphore(name); waiting = 0; last = NULL; } // not supported ~Monitor() {delete sem;}; @@ -577,6 +605,16 @@ class jlib_decl Monitor: public Mutex void notifyAll(); // only called when locked -- notifys for all waiting threads }; +class jlib_decl MonitorBlock +{ +private: + Monitor &monitor; +public: + MonitorBlock(Monitor &m) : monitor(m) { monitor.mutex.lock(); }; + inline ~MonitorBlock() { monitor.mutex.unlock(); }; +}; + + //-------------------------------------------------------------------------------------------------------------------- //Currently disabled since performance profile of own implementation is preferable, and queryWriteLocked() cannot be implemented @@ -838,7 +876,7 @@ class Barrier #define USECHECKEDCRITICALSECTIONS #ifdef USECHECKEDCRITICALSECTIONS -typedef Mutex CheckedCriticalSection; +typedef TimedMutex CheckedCriticalSection; void jlib_decl checkedCritEnter(CheckedCriticalSection &crit, unsigned timeout, const char *fname, unsigned lnum); void jlib_decl checkedCritLeave(CheckedCriticalSection &crit); class jlib_decl CheckedCriticalBlock diff --git a/system/jlib/jpqueue.hpp b/system/jlib/jpqueue.hpp index 3b96b419020..f2c0122e2b4 100644 --- a/system/jlib/jpqueue.hpp +++ b/system/jlib/jpqueue.hpp @@ -30,7 +30,7 @@ #include #include -template class WaitQueue: public CInterface, protected Mutex +template class WaitQueue: public CInterface { public: WaitQueue(): counter(), stopped(false), waiting(0) @@ -40,7 +40,7 @@ template class WaitQueue: public CInterface, protected Mutex ~WaitQueue() { stop(); - synchronized block(*this); + synchronized block(mutex); while(waiting) { counter.signal(waiting); // actually need only one and only once @@ -50,13 +50,13 @@ template class WaitQueue: public CInterface, protected Mutex unsigned size() { - synchronized block(*this); + synchronized block(mutex); return queue.size(); } T get(unsigned timeout=INFINITE) { - synchronized block(*this); + synchronized block(mutex); for(;;) { if(stopped) @@ -73,7 +73,7 @@ template class WaitQueue: public CInterface, protected Mutex bool put(const T& item) { - synchronized block(*this); + synchronized block(mutex); if(stopped) return true; queue.push_back(item); @@ -83,7 +83,7 @@ template class WaitQueue: public CInterface, protected Mutex void stop() { - synchronized block(*this); + synchronized block(mutex); stopped=true; queue.clear(); counter.signal(waiting); @@ -91,7 +91,7 @@ template class WaitQueue: public CInterface, protected Mutex bool isStopped() { - synchronized block(*this); + synchronized block(mutex); return stopped; } @@ -102,14 +102,15 @@ template class WaitQueue: public CInterface, protected Mutex bool ret=false; waiting++; - int locked = unlockAll(); + mutex.unlock(); ret=counter.wait(timeout); - lockAll(locked); + mutex.lock(); waiting--; return ret; } + Mutex mutex; Semaphore counter; std::list queue; volatile unsigned waiting; @@ -146,7 +147,7 @@ class TaskQueue bool needthread=!queue.put(task); if(needthread) { - synchronized block(mworkers); + MonitorBlock block(mworkers); if(workers.size()stop(); // no good if threads did not clean up } void join() { - synchronized block(mworkers); + MonitorBlock block(mworkers); while(!workers.empty()) { mworkers.wait(); @@ -248,7 +249,7 @@ class TaskQueue void remove(WorkerThread* th) { - synchronized block(mworkers); + MonitorBlock block(mworkers); workers.remove(th); if(workers.empty()) mworkers.notifyAll(); diff --git a/system/mp/mpcomm.cpp b/system/mp/mpcomm.cpp index 6355baa5a15..f4d7e9f1281 100644 --- a/system/mp/mpcomm.cpp +++ b/system/mp/mpcomm.cpp @@ -917,7 +917,7 @@ class CMPChannel: public CInterface { ISocket *channelsock = nullptr; CMPServer *parent; - Mutex sendmutex; + TimedMutex sendmutex; Semaphore sendwaitingsig; unsigned sendwaiting = 0; // number waiting on sendwaitingsem (for multi/single clashes to resolve) CriticalSection connectsect; @@ -1627,7 +1627,7 @@ class MultiPacketHandler // TAG_SYS_MULTI } return msg; } - bool send(CMPChannel *channel,PacketHeader &hdr,MemoryBuffer &mb, CTimeMon &tm, Mutex &sendmutex) + bool send(CMPChannel *channel,PacketHeader &hdr,MemoryBuffer &mb, CTimeMon &tm, TimedMutex &sendmutex) { // must not adjust mb #ifdef _FULLTRACE @@ -2045,12 +2045,12 @@ bool CMPChannel::send(MemoryBuffer &mb, mptag_t tag, mptag_t replytag, CTimeMon struct Cpostcondition // can we start using eiffel { - Mutex &sendmutex; + TimedMutex &sendmutex; unsigned &sendwaiting; Semaphore &sendwaitingsig; mptag_t *multitag; - Cpostcondition(Mutex &_sendmutex,unsigned &_sendwaiting,Semaphore &_sendwaitingsig,mptag_t *_multitag) + Cpostcondition(TimedMutex &_sendmutex,unsigned &_sendwaiting,Semaphore &_sendwaitingsig,mptag_t *_multitag) : sendmutex(_sendmutex),sendwaiting(_sendwaiting),sendwaitingsig(_sendwaitingsig) { multitag = _multitag; diff --git a/system/security/LdapSecurity/ldapconnection.cpp b/system/security/LdapSecurity/ldapconnection.cpp index 3c55315f9a6..aaf426e8d67 100644 --- a/system/security/LdapSecurity/ldapconnection.cpp +++ b/system/security/LdapSecurity/ldapconnection.cpp @@ -1077,7 +1077,7 @@ class CLdapConnectionPool : implements ILdapConnectionPool, public CInterface virtual ILdapConnection* getConnection() { - synchronized block(m_monitor); + MonitorBlock block(m_monitor); ForEachItemIn(x, m_connections) { CLdapConnection* curcon = (CLdapConnection*)&(m_connections.item(x)); diff --git a/system/security/LdapSecurity/ldapsecurity.cpp b/system/security/LdapSecurity/ldapsecurity.cpp index 7bd62e4e3d0..01d9a2b04e7 100644 --- a/system/security/LdapSecurity/ldapsecurity.cpp +++ b/system/security/LdapSecurity/ldapsecurity.cpp @@ -1202,7 +1202,7 @@ ISecUser * CLdapSecManager::findUser(const char * username, IEspSecureContext* s ISecUserIterator * CLdapSecManager::getAllUsers(IEspSecureContext* secureContext) { - synchronized block(m_monitor); + MonitorBlock block(m_monitor); m_user_array.popAll(true); m_ldap_client->retrieveUsers(m_user_array); return new ArrayIIteratorOf(m_user_array); diff --git a/system/security/LdapSecurity/permissions.cpp b/system/security/LdapSecurity/permissions.cpp index b268524f9e0..50c8c8ce356 100644 --- a/system/security/LdapSecurity/permissions.cpp +++ b/system/security/LdapSecurity/permissions.cpp @@ -173,7 +173,7 @@ void PermissionProcessor::getCachedSid(const char* name, MemoryBuffer& sid) StringBuffer buf; if(toXpath(name, buf)) { - synchronized block(m_monitor); + MonitorBlock block(m_monitor); try { m_sidcache->getPropBin(buf.str(), sid); @@ -200,7 +200,7 @@ void PermissionProcessor::cacheSid(const char* name, int len, const void* sidbuf StringBuffer buf; if(toXpath(name, buf)) { - synchronized block(m_monitor); + MonitorBlock block(m_monitor); try { if(!m_sidcache->hasProp(buf.str())) diff --git a/testing/unittests/jlibtests.cpp b/testing/unittests/jlibtests.cpp index c98b58521b5..ad579e38092 100644 --- a/testing/unittests/jlibtests.cpp +++ b/testing/unittests/jlibtests.cpp @@ -3259,6 +3259,14 @@ class AtomicTimingStressTest : public CppUnit::TestFixture DO_TEST(Mutex, synchronized, unsigned __int64, 2, 1); DO_TEST(Mutex, synchronized, unsigned __int64, 5, 1); DO_TEST(Mutex, synchronized, unsigned __int64, 1, 2); + DO_TEST(SimpleMutex, MutexBlock, unsigned __int64, 1, 1); + DO_TEST(SimpleMutex, MutexBlock, unsigned __int64, 2, 1); + DO_TEST(SimpleMutex, MutexBlock, unsigned __int64, 5, 1); + DO_TEST(SimpleMutex, MutexBlock, unsigned __int64, 1, 2); + DO_TEST(TimedMutex, TimedMutexBlock, unsigned __int64, 1, 1); + DO_TEST(TimedMutex, TimedMutexBlock, unsigned __int64, 2, 1); + DO_TEST(TimedMutex, TimedMutexBlock, unsigned __int64, 5, 1); + DO_TEST(TimedMutex, TimedMutexBlock, unsigned __int64, 1, 2); DO_TEST(SpinLock, SpinBlock, unsigned __int64, 1, 1); DO_TEST(SpinLock, SpinBlock, unsigned __int64, 2, 1); DO_TEST(SpinLock, SpinBlock, unsigned __int64, 5, 1); @@ -3294,10 +3302,10 @@ class AtomicTimingStressTest : public CppUnit::TestFixture void summariseTimings(const char * option, UInt64Array & times) { - DBGLOG("%11s 1x: cs(%3" I64F "u) spin(%3" I64F "u) atomic(%3" I64F "u) ratomic(%3" I64F "u) cas(%3" I64F "u) rd(%3" I64F "u) wr(%3" I64F "u) " - "5x: cs(%3" I64F "u) spin(%3" I64F "u) atomic(%3" I64F "u) ratomic(%3" I64F "u) cas(%3" I64F "u) rd(%3" I64F "u) wr(%3" I64F "u)", option, - times.item(0), times.item(4), times.item(8), times.item(12), times.item(14), times.item(19), times.item(23), - times.item(2), times.item(6), times.item(10), times.item(13), times.item(15), times.item(21), times.item(25)); + DBGLOG("%11s 1x: cs(%3" I64F "u) mutex (%3" I64F "u) smutex (%3" I64F "u) tmutex (%3" I64F "u) spin(%3" I64F "u) atomic(%3" I64F "u) ratomic(%3" I64F "u) cas(%3" I64F "u) rd(%3" I64F "u) wr(%3" I64F "u)", option, + times.item(0), times.item(4), times.item(8), times.item(12), times.item(16), times.item(20), times.item(24), times.item(26), times.item(31), times.item(35)); + DBGLOG("%11s 5x: cs(%3" I64F "u) mutex (%3" I64F "u) smutex (%3" I64F "u) tmutex (%3" I64F "u) spin(%3" I64F "u) atomic(%3" I64F "u) ratomic(%3" I64F "u) cas(%3" I64F "u) rd(%3" I64F "u) wr(%3" I64F "u)", "", + times.item(2), times.item(6), times.item(10), times.item(14), times.item(18), times.item(22), times.item(25), times.item(27), times.item(33), times.item(37)); } private: