/* Copyright (C) 2000-2002 Stefan Westerfeld stefan@space.twc.de 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; } }