From 75a155bfed5cb800c2a4561450aec93b27c3332f Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 13 Jan 2023 14:45:37 +0000 Subject: [PATCH] ProcStats : Use mutex lock to make fetch() thread safe. : Also minor cleanup and general code modernisation. --- GaudiAud/src/ProcStats.cpp | 56 +++++++++++++-------------- GaudiAud/src/ProcStats.h | 77 ++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 67 deletions(-) diff --git a/GaudiAud/src/ProcStats.cpp b/GaudiAud/src/ProcStats.cpp index 92ad303cf4..60fb0e7bd8 100644 --- a/GaudiAud/src/ProcStats.cpp +++ b/GaudiAud/src/ProcStats.cpp @@ -18,6 +18,7 @@ #endif #include "ProcStats.h" +#include <memory> #if defined( __linux__ ) or defined( __APPLE__ ) # include <iostream> @@ -239,55 +240,50 @@ struct linux_proc { }; #endif // __linux__ or __APPLE__ -ProcStats::cleanup::~cleanup() { - if ( ProcStats::inst != 0 ) { - delete ProcStats::inst; - ProcStats::inst = 0; - } -} - ProcStats* ProcStats::instance() { - static cleanup c; - if ( !inst ) inst = new ProcStats; - return inst; + static std::once_flag alloc_instance_once; + static std::unique_ptr<ProcStats> inst; + std::call_once( alloc_instance_once, []() { inst = std::make_unique<ProcStats>(); } ); + return inst.get(); } -ProcStats* ProcStats::inst = 0; - -ProcStats::ProcStats() : valid( false ) { +ProcStats::ProcStats() { #if defined( __linux__ ) or defined( __APPLE__ ) - pg_size = sysconf( _SC_PAGESIZE ); // getpagesize(); + m_pg_size = sysconf( _SC_PAGESIZE ); // getpagesize(); - fname = "/proc/" + std::to_string( getpid() ) + "/stat"; + m_fname = "/proc/" + std::to_string( getpid() ) + "/stat"; - fd.open( fname.c_str(), O_RDONLY ); - if ( !fd ) { - cerr << "Failed to open " << fname << endl; + m_ufd.open( m_fname.c_str(), O_RDONLY ); + if ( !m_ufd ) { + cerr << "Failed to open " << m_fname << endl; return; } #endif // __linux__ or __APPLE__ - valid = true; + m_valid = true; } bool ProcStats::fetch( procInfo& f ) { - if ( valid == false ) return false; + if ( !m_valid ) { return false; } #if defined( __linux__ ) or defined( __APPLE__ ) - double pr_size, pr_rssize; + + std::scoped_lock lock{ m_mutex }; + + double pr_size{ 0 }, pr_rssize{ 0 }; linux_proc pinfo; - int cnt; + int cnt{ 0 }; - fd.lseek( 0, SEEK_SET ); + m_ufd.lseek( 0, SEEK_SET ); - if ( ( cnt = fd.read( buf, sizeof( buf ) ) ) < 0 ) { + if ( ( cnt = m_ufd.read( m_buf, sizeof( m_buf ) ) ) < 0 ) { cout << "LINUX Read of Proc file failed:" << endl; return false; } if ( cnt > 0 ) { - buf[std::min( static_cast<std::size_t>( cnt ), sizeof( buf ) - 1 )] = '\0'; + m_buf[std::min( static_cast<std::size_t>( cnt ), sizeof( m_buf ) - 1 )] = '\0'; - sscanf( buf, + sscanf( m_buf, // 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 // 30 1 2 3 4 5 "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu " @@ -304,7 +300,7 @@ bool ProcStats::fetch( procInfo& f ) { pr_rssize = (double)pinfo.rss; f.vsize = pr_size / ( 1024 * 1024 ); - f.rss = pr_rssize * pg_size / ( 1024 * 1024 ); + f.rss = pr_rssize * m_pg_size / ( 1024 * 1024 ); } #else @@ -312,10 +308,10 @@ bool ProcStats::fetch( procInfo& f ) { f.rss = 0; #endif // __linux__ or __APPLE__ - bool rc = ( curr == f ) ? false : true; + const bool rc = !( m_curr == f ); - curr.rss = f.rss; - curr.vsize = f.vsize; + m_curr.rss = f.rss; + m_curr.vsize = f.vsize; return rc; } diff --git a/GaudiAud/src/ProcStats.h b/GaudiAud/src/ProcStats.h index 1127540822..067c9e4173 100644 --- a/GaudiAud/src/ProcStats.h +++ b/GaudiAud/src/ProcStats.h @@ -8,15 +8,17 @@ * granted to it by virtue of its status as an Intergovernmental Organization * * or submit itself to any jurisdiction. * \***********************************************************************************/ -#ifndef GAUDIAUD_PROCSTATS_H -#define GAUDIAUD_PROCSTATS_H + +#pragma once // Class: ProcStats // Description: Keeps statistics on memory usage // Author: Jim Kowalkowski (FNAL), modified by M. Shapiro (LBNL) +#include <mutex> #include <string> #include <vector> + #if defined( __linux__ ) or defined( __APPLE__ ) # include <fcntl.h> # include <sys/stat.h> @@ -25,7 +27,7 @@ #endif // __linux__ or __APPLE__ struct procInfo { - procInfo() : vsize( 0 ), rss( 0 ) {} + procInfo() = default; procInfo( double sz, double rss_sz ) : vsize( sz ), rss( rss_sz ) {} bool operator==( const procInfo& p ) const { @@ -35,7 +37,7 @@ struct procInfo { # pragma warning( disable : 1572 ) #endif - return vsize == p.vsize && rss == p.rss; + return ( vsize == p.vsize && rss == p.rss ); #ifdef __ICC // re-enable icc remark #1572 @@ -44,29 +46,23 @@ struct procInfo { } // see proc(4) man pages for units and a description - double vsize; // in MB (used to be in pages?) - double rss; // in MB (used to be in pages?) + double vsize{ 0 }; // in MB (used to be in pages?) + double rss{ 0 }; // in MB (used to be in pages?) }; class ProcStats { public: static ProcStats* instance(); - bool fetch( procInfo& fill_me ); - double pageSize() const { return pg_size; } - -private: + bool fetch( procInfo& fill_me ); + auto pageSize() const noexcept { return m_pg_size; } ProcStats(); - struct cleanup { - cleanup() {} - ~cleanup(); - }; - - friend struct cleanup; - +private: class unique_fd { - int m_fd; + + private: + int m_fd{ -1 }; unique_fd( const unique_fd& ) = delete; unique_fd& operator=( const unique_fd& ) = delete; @@ -77,7 +73,7 @@ private: other.m_fd = -1; } ~unique_fd() { - if ( m_fd != -1 ) ::close( m_fd ); + if ( m_fd != -1 ) { ::close( m_fd ); } } explicit operator bool() const { return m_fd != -1; } @@ -86,29 +82,36 @@ private: m_fd = ::open( std::forward<Args>( args )... ); return *this; } + + int close() { + auto r = ::close( m_fd ); + m_fd = -1; + return r; + } + + public: #define unique_fd_forward( fun ) \ template <typename... Args> \ - auto fun( Args&&... args ) const->decltype( ::fun( m_fd, std::forward<Args>( args )... ) ) { \ + auto fun( Args&&... args ) const { \ return ::fun( m_fd, std::forward<Args>( args )... ); \ } - unique_fd_forward( lseek ) unique_fd_forward( read ) unique_fd_forward( write ) unique_fd_forward( fcntl ) - unique_fd_forward( fsync ) unique_fd_forward( fchown ) unique_fd_forward( stat ) + // clang-format off + unique_fd_forward( lseek ) + unique_fd_forward( read ) + unique_fd_forward( write ) + unique_fd_forward( fcntl ) + unique_fd_forward( fsync ) + unique_fd_forward( fchown ) + unique_fd_forward( stat ) + // clang-format on #undef unique_fd_forward - int close() { - auto r = ::close( m_fd ); - m_fd = -1; - return r; - } }; - unique_fd fd; - double pg_size; - procInfo curr; - std::string fname; - char buf[500]; - bool valid; - - static ProcStats* inst; + unique_fd m_ufd; + double m_pg_size{ 0 }; + procInfo m_curr; + std::string m_fname; + char m_buf[500]; + bool m_valid{ false }; + std::mutex m_mutex; }; - -#endif -- GitLab