diff options
Diffstat (limited to 'soundserver/cpuusage.cpp')
-rw-r--r-- | soundserver/cpuusage.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/soundserver/cpuusage.cpp b/soundserver/cpuusage.cpp new file mode 100644 index 0000000..c08baba --- /dev/null +++ b/soundserver/cpuusage.cpp @@ -0,0 +1,137 @@ + /* + + Copyright (C) 2000-2002 Stefan Westerfeld + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "cpuusage.h" +#include "dispatcher.h" +#include "debug.h" + +#include <time.h> +#include <unistd.h> +#include <sys/time.h> +#include <signal.h> + +#include <iostream> + +using namespace std; + +namespace Arts { + +class Benchmark +{ +private: + struct timeval _start,_stop; +public: + void start() + { + gettimeofday(&_start,NULL); + } + float stop() + { + gettimeofday(&_stop,NULL); + + float diff = _stop.tv_sec-_start.tv_sec; + diff += (float)(_stop.tv_usec-_start.tv_usec)/1000000; + return diff; + } +}; + +class CPUUsagePrivate +{ +public: + clock_t oldclock; + int stalled; + float usage; + Benchmark b; +}; + +/** signal handlers **/ + +static CPUUsage *cpuUsage = 0; + +extern "C" void cpuUsageCheck(int) +{ + if(cpuUsage != 0) + cpuUsage->check(); + + signal(SIGALRM, cpuUsageCheck); +} + +/** main stuff **/ + +CPUUsage::CPUUsage() : d(new CPUUsagePrivate()) +{ + d->oldclock = clock(); + d->usage = 0; + d->stalled = 0; + d->b.start(); + cpuUsage = this; + + /* setup signal handler & timer */ + + struct itimerval oldvalue; + struct itimerval newvalue = {{ 1, 0 }, {1, 0}}; // 1 second + + setitimer(ITIMER_REAL, &newvalue, &oldvalue); + signal(SIGALRM, cpuUsageCheck); +} + +CPUUsage::~CPUUsage() +{ + delete d; + cpuUsage = 0; +} + +float CPUUsage::usage() +{ + return d->usage; +} + +void CPUUsage::check() +{ + float cpu_time = (clock()-d->oldclock)/(float)CLOCKS_PER_SEC; + float real_time = d->b.stop(); + + if(cpu_time > 0 && real_time > 0) // there may be wraparounds + { + d->usage = cpu_time / real_time; + + if(d->usage > 0.95) // more than 95% -> not good! (probably freeze) + d->stalled++; + else + d->stalled=0; + + // ok, cancel synthesis due to cpu overload! brutal method + if(d->stalled > 15) + arts_fatal("cpu overload, aborting"); + } + + // prepare for next checkpoint + d->oldclock = clock(); + d->b.start(); +} + +CPUUsage *CPUUsage::the() +{ + return cpuUsage; +} + +} |