1 | /*␊ |
2 | * This file is part of the libpayload project.␊ |
3 | *␊ |
4 | * Copyright (C) 2008 Advanced Micro Devices, Inc.␊ |
5 | *␊ |
6 | * Redistribution and use in source and binary forms, with or without␊ |
7 | * modification, are permitted provided that the following conditions␊ |
8 | * are met:␊ |
9 | * 1. Redistributions of source code must retain the above copyright␊ |
10 | * notice, this list of conditions and the following disclaimer.␊ |
11 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
12 | * notice, this list of conditions and the following disclaimer in the␊ |
13 | * documentation and/or other materials provided with the distribution.␊ |
14 | * 3. The name of the author may not be used to endorse or promote products␊ |
15 | * derived from this software without specific prior written permission.␊ |
16 | *␊ |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND␊ |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE␊ |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE␊ |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS␊ |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)␊ |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT␊ |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY␊ |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF␊ |
27 | * SUCH DAMAGE.␊ |
28 | */␊ |
29 | ␊ |
30 | /**␊ |
31 | * @file libc/time.c␊ |
32 | * General time functions␊ |
33 | */␊ |
34 | #include "libsaio.h"␊ |
35 | #include "cpu.h"␊ |
36 | #include "platform.h"␊ |
37 | ␊ |
38 | ␊ |
39 | static uint32_t cpu_khz;␊ |
40 | ␊ |
41 | static struct {␊ |
42 | ␉uint64_t ticks;␊ |
43 | ␉time_t secs;␊ |
44 | ␉suseconds_t usecs;␊ |
45 | } private_clock;␊ |
46 | ␊ |
47 | #define TICKS_PER_SEC (cpu_khz * 1000)␊ |
48 | #define TICKS_PER_USEC (cpu_khz / 1000)␊ |
49 | ␊ |
50 | static void update_clock(void)␊ |
51 | {␊ |
52 | ␉uint64_t delta = rdtsc64() - private_clock.ticks;␊ |
53 | ␉int secs;␊ |
54 | ␊ |
55 | ␉private_clock.ticks += delta;␊ |
56 | ␊ |
57 | ␉secs = (int) (delta / TICKS_PER_SEC);␊ |
58 | ␉private_clock.secs += secs;␊ |
59 | ␉delta -= (secs * TICKS_PER_SEC);␊ |
60 | ␉private_clock.usecs += (int) (delta / TICKS_PER_USEC);␊ |
61 | ␊ |
62 | ␉if (private_clock.usecs > 1000000) {␊ |
63 | ␉␉private_clock.usecs -= 1000000;␊ |
64 | ␉␉private_clock.secs++;␊ |
65 | ␉}␊ |
66 | }␊ |
67 | ␊ |
68 | static unsigned int day_of_year(int mon, int day, int year)␊ |
69 | {␊ |
70 | ␉static uint8_t mdays[12] = { 31, 28, 31, 30, 31, 30,␊ |
71 | ␉␉␉␉31, 31, 30, 31, 30, 31 };␊ |
72 | ␊ |
73 | ␉int i, ret = 0;␊ |
74 | ␊ |
75 | ␉for(i = 0; i < mon; i++) {␊ |
76 | ␉␉ret += mdays[i];␊ |
77 | ␊ |
78 | ␉␉if (i == 1 && (year % 4))␊ |
79 | ␉␉␉ret++;␊ |
80 | ␉}␊ |
81 | ␊ |
82 | ␉return (ret + day);␊ |
83 | }␊ |
84 | ␊ |
85 | static void gettimeofday_init(void)␊ |
86 | {␊ |
87 | ␉int days, delta;␊ |
88 | ␉struct tm tm;␊ |
89 | ␊ |
90 | ␉rtc_read_clock(&tm);␊ |
91 | ␉private_clock.ticks = rdtsc64();␊ |
92 | ␊ |
93 | ␉/* Calculate the number of days in the year so far */␊ |
94 | ␉days = day_of_year(tm.tm_mon, tm.tm_mday, tm.tm_year + 1900);␊ |
95 | ␊ |
96 | ␉delta = tm.tm_year - 70;␊ |
97 | ␊ |
98 | ␉days += (delta * 365);␊ |
99 | ␊ |
100 | ␉/* Figure leap years */␊ |
101 | ␊ |
102 | ␉if (delta > 2)␊ |
103 | ␉ days += (delta - 2) / 4;␊ |
104 | ␊ |
105 | ␉private_clock.secs = (days * 86400) + (tm.tm_hour * 3600) +␊ |
106 | ␉␉(tm.tm_min * 60) + tm.tm_sec;␊ |
107 | }␊ |
108 | ␊ |
109 | /**␊ |
110 | * Return the current time broken into a timeval structure.␊ |
111 | *␊ |
112 | * @param tv A pointer to a timeval structure.␊ |
113 | * @param tz Added for compatability - not used.␊ |
114 | * @return 0 for success (this function cannot return non-zero currently).␊ |
115 | *␊ |
116 | * WARNING : In this implementation gettimeofday() will not work until the cpu is not initialized.␊ |
117 | */␊ |
118 | int gettimeofday(struct timeval *tv, void *tz)␊ |
119 | {␊ |
120 | cpu_khz = (uint32_t)(get_env(envCPUFreq) / 1000);␊ |
121 | if (!(cpu_khz>0)) {␊ |
122 | return 1;␊ |
123 | }␊ |
124 | ␉/*␊ |
125 | ␉ * Call the gtod init when we need it - this keeps the code from␊ |
126 | ␉ * being included in the binary if we don't need it.␊ |
127 | ␉ */␊ |
128 | ␉if (!private_clock.ticks)␊ |
129 | ␉␉gettimeofday_init();␊ |
130 | ␊ |
131 | ␉update_clock();␊ |
132 | ␊ |
133 | ␉tv->tv_sec = private_clock.secs;␊ |
134 | ␉tv->tv_usec = private_clock.usecs;␊ |
135 | ␊ |
136 | ␉return 0;␊ |
137 | }␊ |
138 | |