From 840fba7672db59fb836de407a3a0bf28eca4e114 Mon Sep 17 00:00:00 2001 From: "Troshin V.S" Date: Tue, 25 Mar 2014 18:35:59 +0100 Subject: [PATCH] CLI: Add -l command line option --- cli/cmdlineparser.cpp | 26 ++++++++++++++++++++++++++ cli/threadexecutor.cpp | 30 +++++++++++++++++++++++++++--- cli/threadexecutor.h | 7 +++++++ lib/settings.cpp | 1 + lib/settings.h | 3 +++ 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index bbca3a8b9..9f1c3edf3 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -576,6 +576,29 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) PrintMessage("cppcheck: argument for '-j' is allowed to be 10000 at max."); return false; } + } else if (std::strncmp(argv[i], "-l", 2) == 0) { + std::string numberString; + + // "-l 3" + if (std::strcmp(argv[i], "-l") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + PrintMessage("cppcheck: argument to '-l' is missing."); + return false; + } + + numberString = argv[i]; + } + + // "-l3" + else + numberString = argv[i]+2; + + std::istringstream iss(numberString); + if (!(iss >> _settings->_loadAverage)) { + PrintMessage("cppcheck: argument to '-l' is not a number."); + return false; + } } // print all possible error messages.. @@ -869,6 +892,9 @@ void CmdLineParser::PrintHelp() " more comments, like: '// cppcheck-suppress warningId'\n" " on the lines before the warning to suppress.\n" " -j Start [jobs] threads to do the checking simultaneously.\n" + " -l Specifies that no new threads should be started if there\n" + " are other threads running and the load average is at least\n" + " load (ignored on non UNIX-like systems)\n" " --language=, -x \n" " Forces cppcheck to check all files as the given\n" " language. Valid values are: c, c++\n" diff --git a/cli/threadexecutor.cpp b/cli/threadexecutor.cpp index f4c62de09..b970e2d70 100644 --- a/cli/threadexecutor.cpp +++ b/cli/threadexecutor.cpp @@ -138,6 +138,22 @@ int ThreadExecutor::handleRead(int rpipe, unsigned int &result) return 1; } +bool ThreadExecutor::checkLoadAverage(size_t nchilds) +{ + if (!nchilds || !_settings._loadAverage) { + return true; + } + + double sample; + if (getloadavg(&sample, 1) != 1) { + // disable load average cheking on getloadavg error + return true; + } else if (sample < _settings._loadAverage) { + return true; + } + return false; +} + unsigned int ThreadExecutor::check() { _fileCount = 0; @@ -155,7 +171,8 @@ unsigned int ThreadExecutor::check() std::map::const_iterator i = _files.begin(); for (;;) { // Start a new child - if (i != _files.end() && rpipes.size() < _settings._jobs) { + size_t nchilds = rpipes.size(); + if (i != _files.end() && nchilds < _settings._jobs && checkLoadAverage(nchilds)) { int pipes[2]; if (pipe(pipes) == -1) { std::cerr << "pipe() failed: "<< std::strerror(errno) << std::endl; @@ -211,8 +228,10 @@ unsigned int ThreadExecutor::check() FD_ZERO(&rfds); for (std::list::const_iterator rp = rpipes.begin(); rp != rpipes.end(); ++rp) FD_SET(*rp, &rfds); - - int r = select(*std::max_element(rpipes.begin(), rpipes.end()) + 1, &rfds, NULL, NULL, NULL); + struct timeval tv; // for every second polling of load average condition + tv.tv_sec = 1; + tv.tv_usec = 0; + int r = select(*std::max_element(rpipes.begin(), rpipes.end()) + 1, &rfds, NULL, NULL, &tv); if (r > 0) { std::list::iterator rp = rpipes.begin(); @@ -320,6 +339,11 @@ void ThreadExecutor::addFileContent(const std::string &path, const std::string & _fileContents[path] = content; } +bool ThreadExecutor::checkLoadAverage(size_t nchilds) +{ + return true; +} + unsigned int ThreadExecutor::check() { HANDLE *threadHandles = new HANDLE[_settings._jobs]; diff --git a/cli/threadexecutor.h b/cli/threadexecutor.h index c500024ba..a5e949018 100644 --- a/cli/threadexecutor.h +++ b/cli/threadexecutor.h @@ -87,6 +87,13 @@ private: std::list _errorList; int _wpipe; + /** + * @brief Check load average condition + * @param nchilds - count of currently runned childs + * @return true - if new process can be started + */ + bool checkLoadAverage(size_t nchilds); + public: /** * @return true if support for threads exist. diff --git a/lib/settings.cpp b/lib/settings.cpp index b8f06cd08..a383b786d 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -34,6 +34,7 @@ Settings::Settings() _relativePaths(false), _xml(false), _xml_version(1), _jobs(1), + _loadAverage(0), _exitCode(0), _showtime(SHOWTIME_NONE), _maxConfigs(12), diff --git a/lib/settings.h b/lib/settings.h index 94c5c35ba..16c03679d 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -115,6 +115,9 @@ public: time. Default is 1. (-j N) */ unsigned int _jobs; + /** @brief Load average value */ + unsigned int _loadAverage; + /** @brief If errors are found, this value is returned from main(). Default value is 0. */ int _exitCode;