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