timer.cc revision 9655
19651SAndreas.Sandberg@ARM.com/* 29651SAndreas.Sandberg@ARM.com * Copyright (c) 2012 ARM Limited 39651SAndreas.Sandberg@ARM.com * All rights reserved 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 69651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 79651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 89651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 99651SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 109651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 119651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 129651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 139651SAndreas.Sandberg@ARM.com * 149651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 159651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 169651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 179651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 189651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 199651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 209651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 219651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 229651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 239651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 249651SAndreas.Sandberg@ARM.com * 259651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369651SAndreas.Sandberg@ARM.com * 379651SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg 389651SAndreas.Sandberg@ARM.com */ 399651SAndreas.Sandberg@ARM.com 409651SAndreas.Sandberg@ARM.com#include <csignal> 419651SAndreas.Sandberg@ARM.com#include <ctime> 429651SAndreas.Sandberg@ARM.com 439651SAndreas.Sandberg@ARM.com#include "base/misc.hh" 449651SAndreas.Sandberg@ARM.com#include "base/trace.hh" 459651SAndreas.Sandberg@ARM.com#include "cpu/kvm/timer.hh" 469651SAndreas.Sandberg@ARM.com#include "debug/KvmTimer.hh" 479651SAndreas.Sandberg@ARM.com 489651SAndreas.Sandberg@ARM.com 499651SAndreas.Sandberg@ARM.comPosixKvmTimer::PosixKvmTimer(int signo, clockid_t clockID, 509651SAndreas.Sandberg@ARM.com float hostFactor, Tick hostFreq) 519651SAndreas.Sandberg@ARM.com : BaseKvmTimer(signo, hostFactor, hostFreq), 529651SAndreas.Sandberg@ARM.com clockID(clockID) 539651SAndreas.Sandberg@ARM.com{ 549651SAndreas.Sandberg@ARM.com struct sigevent sev; 559651SAndreas.Sandberg@ARM.com 569651SAndreas.Sandberg@ARM.com // TODO: We should request signal delivery to thread instead of 579651SAndreas.Sandberg@ARM.com // the process here. Unfortunately this seems to be broken, or at 589651SAndreas.Sandberg@ARM.com // least not work as specified in the man page. 599651SAndreas.Sandberg@ARM.com sev.sigev_notify = SIGEV_SIGNAL; 609651SAndreas.Sandberg@ARM.com sev.sigev_signo = signo; 619651SAndreas.Sandberg@ARM.com sev.sigev_value.sival_ptr = NULL; 629651SAndreas.Sandberg@ARM.com if (timer_create(clockID, &sev, &timer) == -1) 639651SAndreas.Sandberg@ARM.com panic("timer_create"); 649651SAndreas.Sandberg@ARM.com} 659651SAndreas.Sandberg@ARM.com 669651SAndreas.Sandberg@ARM.comPosixKvmTimer::~PosixKvmTimer() 679651SAndreas.Sandberg@ARM.com{ 689651SAndreas.Sandberg@ARM.com timer_delete(timer); 699651SAndreas.Sandberg@ARM.com} 709651SAndreas.Sandberg@ARM.com 719651SAndreas.Sandberg@ARM.comvoid 729651SAndreas.Sandberg@ARM.comPosixKvmTimer::arm(Tick ticks) 739651SAndreas.Sandberg@ARM.com{ 749651SAndreas.Sandberg@ARM.com struct itimerspec ts; 759651SAndreas.Sandberg@ARM.com memset(&ts, 0, sizeof(ts)); 769651SAndreas.Sandberg@ARM.com 779651SAndreas.Sandberg@ARM.com ts.it_interval.tv_sec = 0; 789651SAndreas.Sandberg@ARM.com ts.it_interval.tv_nsec = 0; 799651SAndreas.Sandberg@ARM.com ts.it_value.tv_sec = hostNs(ticks) / 1000000000ULL; 809651SAndreas.Sandberg@ARM.com ts.it_value.tv_nsec = hostNs(ticks) % 1000000000ULL; 819651SAndreas.Sandberg@ARM.com 829651SAndreas.Sandberg@ARM.com DPRINTF(KvmTimer, "Arming POSIX timer: %i ticks (%is%ins)\n", 839651SAndreas.Sandberg@ARM.com ticks, ts.it_value.tv_sec, ts.it_value.tv_nsec); 849651SAndreas.Sandberg@ARM.com 859651SAndreas.Sandberg@ARM.com if (timer_settime(timer, 0, &ts, NULL) == -1) 869651SAndreas.Sandberg@ARM.com panic("PosixKvmTimer: Failed to arm timer\n"); 879651SAndreas.Sandberg@ARM.com} 889651SAndreas.Sandberg@ARM.com 899651SAndreas.Sandberg@ARM.comvoid 909651SAndreas.Sandberg@ARM.comPosixKvmTimer::disarm() 919651SAndreas.Sandberg@ARM.com{ 929651SAndreas.Sandberg@ARM.com struct itimerspec ts; 939651SAndreas.Sandberg@ARM.com memset(&ts, 0, sizeof(ts)); 949651SAndreas.Sandberg@ARM.com 959651SAndreas.Sandberg@ARM.com DPRINTF(KvmTimer, "Disarming POSIX timer\n"); 969651SAndreas.Sandberg@ARM.com 979651SAndreas.Sandberg@ARM.com if (timer_settime(timer, 0, &ts, NULL) == -1) 989651SAndreas.Sandberg@ARM.com panic("PosixKvmTimer: Failed to disarm timer\n"); 999651SAndreas.Sandberg@ARM.com} 1009651SAndreas.Sandberg@ARM.com 1019651SAndreas.Sandberg@ARM.comTick 1029651SAndreas.Sandberg@ARM.comPosixKvmTimer::calcResolution() 1039651SAndreas.Sandberg@ARM.com{ 1049651SAndreas.Sandberg@ARM.com struct timespec ts; 1059651SAndreas.Sandberg@ARM.com 1069651SAndreas.Sandberg@ARM.com if (clock_getres(clockID, &ts) == -1) 1079651SAndreas.Sandberg@ARM.com panic("PosixKvmTimer: Failed to get timer resolution\n"); 1089651SAndreas.Sandberg@ARM.com 1099651SAndreas.Sandberg@ARM.com Tick resolution(ticksFromHostNs(ts.tv_sec * 1000000000ULL + ts.tv_nsec)); 1109651SAndreas.Sandberg@ARM.com 1119651SAndreas.Sandberg@ARM.com return resolution; 1129651SAndreas.Sandberg@ARM.com} 1139655SAndreas.Sandberg@ARM.com 1149655SAndreas.Sandberg@ARM.com 1159655SAndreas.Sandberg@ARM.comPerfKvmTimer::PerfKvmTimer(PerfKvmCounter &ctr, 1169655SAndreas.Sandberg@ARM.com int signo, float hostFactor, Tick hostFreq) 1179655SAndreas.Sandberg@ARM.com : BaseKvmTimer(signo, hostFactor, hostFreq), 1189655SAndreas.Sandberg@ARM.com hwOverflow(ctr) 1199655SAndreas.Sandberg@ARM.com{ 1209655SAndreas.Sandberg@ARM.com hwOverflow.enableSignals(signo); 1219655SAndreas.Sandberg@ARM.com} 1229655SAndreas.Sandberg@ARM.com 1239655SAndreas.Sandberg@ARM.comPerfKvmTimer::~PerfKvmTimer() 1249655SAndreas.Sandberg@ARM.com{ 1259655SAndreas.Sandberg@ARM.com} 1269655SAndreas.Sandberg@ARM.com 1279655SAndreas.Sandberg@ARM.comvoid 1289655SAndreas.Sandberg@ARM.comPerfKvmTimer::arm(Tick ticks) 1299655SAndreas.Sandberg@ARM.com{ 1309655SAndreas.Sandberg@ARM.com hwOverflow.period(hostCycles(ticks)); 1319655SAndreas.Sandberg@ARM.com hwOverflow.refresh(1); 1329655SAndreas.Sandberg@ARM.com} 1339655SAndreas.Sandberg@ARM.com 1349655SAndreas.Sandberg@ARM.comvoid 1359655SAndreas.Sandberg@ARM.comPerfKvmTimer::disarm() 1369655SAndreas.Sandberg@ARM.com{ 1379655SAndreas.Sandberg@ARM.com hwOverflow.stop(); 1389655SAndreas.Sandberg@ARM.com} 1399655SAndreas.Sandberg@ARM.com 1409655SAndreas.Sandberg@ARM.comTick 1419655SAndreas.Sandberg@ARM.comPerfKvmTimer::calcResolution() 1429655SAndreas.Sandberg@ARM.com{ 1439655SAndreas.Sandberg@ARM.com // This is a bit arbitrary, but in practice, we can't really do 1449655SAndreas.Sandberg@ARM.com // anything useful in less than ~1000 anyway. 1459655SAndreas.Sandberg@ARM.com return ticksFromHostCycles(1000); 1469655SAndreas.Sandberg@ARM.com} 147