The Pedigree Project 0.1
Time.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/LockGuard.h"
21#include "pedigree/kernel/Spinlock.h"
22#include "pedigree/kernel/machine/Machine.h"
23#include "pedigree/kernel/machine/Timer.h"
24#include "pedigree/kernel/process/InfoBlock.h"
25#include "pedigree/kernel/processor/Processor.h"
26#include "pedigree/kernel/time/Time.h"
27
28#if X64 && MACH_PC && !HOSTED
29#include "machine/mach_pc/Rtc.h"
30#endif
31
32namespace Time {
33namespace {
34Spinlock realtimeLock(false, true);
35bool realtimeSet = false;
36Timestamp realtimeBase = 0;
37Timestamp monotonicBase = 0;
38} // namespace
39
40Timestamp getTime(bool sync) {
41 return getTimeNanoseconds(sync) / Multiplier::Second;
42}
43
44Timestamp getTimeNanoseconds(bool sync) {
45 Timer* pTimer = Machine::instance().getTimer();
46 if (!pTimer) {
47 return 0;
48 }
49 if (sync)
50 pTimer->synchronise();
51 LockGuard<Spinlock> guard(realtimeLock);
52 if (realtimeSet) {
53 const Timestamp elapsed = pTimer->getTickCountNano() - monotonicBase;
54 return elapsed >= Infinity - realtimeBase ? Infinity - 1 : realtimeBase + elapsed;
55 }
56 Timestamp r = pTimer->getUnixTimestamp() * Multiplier::Second;
57 r += pTimer->getNanosecond();
58 return r;
59}
60
61bool setTimeNanoseconds(Timestamp value) {
62 Timer* timer = Machine::instance().getTimer();
63 if (!timer || value == Infinity) {
64 return false;
65 }
66 {
67 LockGuard<Spinlock> guard(realtimeLock);
68 const Timestamp now = timer->getTickCountNano();
69 if (value < now) {
70 return false;
71 }
72 realtimeBase = value;
73 monotonicBase = now;
74 realtimeSet = true;
75 }
76 // Publish to vDSO readers before the setting syscall returns.
77 InfoBlockManager::instance().refreshTime();
78 return true;
79}
80
81bool anchorRealtime(Timestamp value) {
82 Timer* timer = Machine::instance().getTimer();
83 if (!timer || value == Infinity) {
84 return false;
85 }
86 {
87 LockGuard<Spinlock> guard(realtimeLock);
88 realtimeBase = value;
89 monotonicBase = timer->getTickCountNano();
90 realtimeSet = true;
91 }
92 InfoBlockManager::instance().refreshTime();
93 return true;
94}
95
96Timestamp getTicks() {
97 Timer* pTimer = Machine::instance().getTimer();
98 if (!pTimer) {
99 return 0;
100 }
101 return pTimer->getTickCountNano();
102}
103
104Timestamp getTicksFast() {
105 Timer* pTimer = Machine::instance().getTimer();
106 if (!pTimer) {
107 return 0;
108 }
109 return pTimer->getTickCountNanoFast();
110}
111
112CpuTimeSample sampleCpuTime() {
113#if X64 && MACH_PC && !HOSTED
114 // Pc::getTimer() always selects this clock, including before calibration.
115 // Qualifying the call avoids virtual dispatch at every accounting boundary.
116 return Rtc::instance().Rtc::sampleCpuTime();
117#else
118 Timer* timer = Machine::instance().getTimer();
119 if (!timer) {
120 return {0, Processor::index()};
121 }
122 return timer->sampleCpuTime();
123#endif
124}
125
126} // namespace Time
virtual Timer * getTimer()=0
static size_t index()
virtual uint64_t getTickCountNanoFast()
virtual uint64_t getTickCountNano()
virtual Time::CpuTimeSample sampleCpuTime()
Definition Timer.cc:24
virtual uint64_t getNanosecond()=0
virtual void synchronise(bool tohw=false)
Synchronises the timer with the hardware. Useful for updating the fields returned by get*,...
virtual Time::Timestamp getUnixTimestamp()
Definition Timer.cc:29