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: