diff --git a/iocore/eventsystem/I_Lock.h b/iocore/eventsystem/I_Lock.h index d599be26b06..4850199251d 100644 --- a/iocore/eventsystem/I_Lock.h +++ b/iocore/eventsystem/I_Lock.h @@ -48,13 +48,20 @@ @param _t The current EThread executing your code. */ + +// A weak version of the SCOPED_MUTEX_LOCK macro, allows the mutex to be a nullptr. #ifdef DEBUG -#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(MakeSourceLocation(), nullptr, _m, _t) -#else -#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(_m, _t) +#define WEAK_SCOPED_MUTEX_LOCK(_l, _m, _t) WeakMutexLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t); +#else // DEBUG +#define WEAK_SCOPED_MUTEX_LOCK(_l, _m, _t) WeakMutexLock _l(_m, _t); #endif // DEBUG #ifdef DEBUG +#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) +#else // DEBUG +#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(_m, _t) +#endif // DEBUG + /** Attempts to acquire the lock to the ProxyMutex. @@ -68,8 +75,15 @@ @param _t The current EThread executing your code. */ -#define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) +#ifdef DEBUG +#define WEAK_MUTEX_TRY_LOCK(_l, _m, _t) WeakMutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t); +#else // DEBUG +#define WEAK_MUTEX_TRY_LOCK(_l, _m, _t) WeakMutexTryLock _l(_m, _t); +#endif // DEBUG + +#ifdef DEBUG +#define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) #else // DEBUG #define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(_m, _t) #endif // DEBUG @@ -337,23 +351,21 @@ Mutex_unlock(Ptr &m, EThread *t) } } -/** Scoped lock class for ProxyMutex - */ -class MutexLock +class WeakMutexLock { private: Ptr m; bool locked_p; public: - MutexLock( + WeakMutexLock( #ifdef DEBUG const SourceLocation &location, const char *ahandler, #endif // DEBUG Ptr &am, EThread *t) : m(am), locked_p(true) { - if (am) { + if (m.get()) { Mutex_lock( #ifdef DEBUG location, ahandler, @@ -365,7 +377,42 @@ class MutexLock void release() { - if (locked_p && m) { + if (locked_p && m.get()) { + Mutex_unlock(m, m->thread_holding); + } + locked_p = false; + } + + ~WeakMutexLock() { this->release(); } +}; + +/** Scoped lock class for ProxyMutex + */ +class MutexLock +{ +private: + Ptr m; + bool locked_p; + +public: + MutexLock( +#ifdef DEBUG + const SourceLocation &location, const char *ahandler, +#endif // DEBUG + Ptr &am, EThread *t) + : m(am), locked_p(true) + { + Mutex_lock( +#ifdef DEBUG + location, ahandler, +#endif // DEBUG + m, t); + } + + void + release() + { + if (locked_p) { Mutex_unlock(m, m->thread_holding); } locked_p = false; @@ -376,21 +423,21 @@ class MutexLock /** Scoped try lock class for ProxyMutex */ -class MutexTryLock +class WeakMutexTryLock { private: Ptr m; bool lock_acquired; public: - MutexTryLock( + WeakMutexTryLock( #ifdef DEBUG const SourceLocation &location, const char *ahandler, #endif // DEBUG Ptr &am, EThread *t) : m(am) { - if (am) { + if (m.get()) { lock_acquired = Mutex_trylock( #ifdef DEBUG location, ahandler, @@ -401,11 +448,12 @@ class MutexTryLock } } - ~MutexTryLock() + ~WeakMutexTryLock() { if (lock_acquired && m.get()) { Mutex_unlock(m, m->thread_holding); } + lock_acquired = false; } /** Spin till lock is acquired @@ -441,6 +489,67 @@ class MutexTryLock } }; +/** Scoped try lock class for ProxyMutex + */ +class MutexTryLock +{ +private: + Ptr m; + bool lock_acquired; + +public: + MutexTryLock( +#ifdef DEBUG + const SourceLocation &location, const char *ahandler, +#endif // DEBUG + Ptr &am, EThread *t) + : m(am) + { + lock_acquired = Mutex_trylock( +#ifdef DEBUG + location, ahandler, +#endif // DEBUG + m, t); + } + + ~MutexTryLock() + { + if (lock_acquired) { + Mutex_unlock(m, m->thread_holding); + } + } + + /** Spin till lock is acquired + */ + void + acquire(EThread *t) + { + MUTEX_TAKE_LOCK(m, t); + lock_acquired = true; + } + + void + release() + { + if (lock_acquired) { + Mutex_unlock(m, m->thread_holding); + } + lock_acquired = false; + } + + bool + is_locked() const + { + return lock_acquired; + } + + const ProxyMutex * + get_mutex() const + { + return m.get(); + } +}; + inline void ProxyMutex::free() { diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc index 27a5b1c98fd..991071c1395 100644 --- a/iocore/hostdb/HostDB.cc +++ b/iocore/hostdb/HostDB.cc @@ -994,7 +994,7 @@ HostDBContinuation::removeEvent(int /* event ATS_UNUSED */, Event *e) if (cont) { proxy_mutex = cont->mutex; } - MUTEX_TRY_LOCK(lock, proxy_mutex, e->ethread); + WEAK_MUTEX_TRY_LOCK(lock, proxy_mutex, e->ethread); if (!lock.is_locked()) { e->schedule_in(HOST_DB_RETRY_PERIOD); return EVENT_CONT; diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 112cca4e43f..167731310d9 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -1747,6 +1747,7 @@ SSLNetVConnection::callHooks(TSEvent eventId) } if (curHook != nullptr) { + WEAK_SCOPED_MUTEX_LOCK(lock, curHook->m_cont->mutex, this_ethread()); curHook->invoke(eventId, this); reenabled = (this->sslHandshakeHookState != HANDSHAKE_HOOKS_CERT_INVOKE && this->sslHandshakeHookState != HANDSHAKE_HOOKS_PRE_INVOKE && diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc index 40d5b491d23..af7c30ee2ca 100644 --- a/proxy/ProxySession.cc +++ b/proxy/ProxySession.cc @@ -108,7 +108,7 @@ ProxySession::state_api_callout(int event, void *data) if (nullptr != cur_hook) { APIHook const *hook = cur_hook; - MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding); + WEAK_MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding); // Have a mutex but didn't get the lock, reschedule if (!lock.is_locked()) { diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 793b82f34e3..ba8a3aca32d 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -1463,7 +1463,7 @@ plugins required to work with sni_routing. callout_state = HTTP_API_IN_CALLOUT; } - MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding); + WEAK_MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding); // Have a mutex but didn't get the lock, reschedule if (!lock.is_locked()) { diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index b61fdc0a4d0..dc4d365b831 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -1330,7 +1330,7 @@ APIHook::invoke(int event, void *edata) const ink_assert(!"not reached"); } } - MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread()); + WEAK_MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread()); if (!lock.is_locked()) { // If we cannot get the lock, the caller needs to restructure to handle rescheduling ink_release_assert(0); @@ -4785,7 +4785,7 @@ int TSContCall(TSCont contp, TSEvent event, void *edata) { Continuation *c = (Continuation *)contp; - MUTEX_TRY_LOCK(lock, c->mutex, this_ethread()); + WEAK_MUTEX_TRY_LOCK(lock, c->mutex, this_ethread()); if (!lock.is_locked()) { // If we cannot get the lock, the caller needs to restructure to handle rescheduling ink_release_assert(0); diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index 591ce0b0c49..d6095ab4d42 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -230,7 +230,7 @@ struct AutoStopCont : public Continuation { APIHook *hook = lifecycle_hooks->get(TS_LIFECYCLE_SHUTDOWN_HOOK); while (hook) { - SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); + WEAK_SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); hook->invoke(TS_EVENT_LIFECYCLE_SHUTDOWN, nullptr); hook = hook->next(); } @@ -2113,7 +2113,7 @@ task_threads_started_callback() { APIHook *hook = lifecycle_hooks->get(TS_LIFECYCLE_TASK_THREADS_READY_HOOK); while (hook) { - SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); + WEAK_SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); hook->invoke(TS_EVENT_LIFECYCLE_TASK_THREADS_READY, nullptr); hook = hook->next(); }