OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(HOST_OS_FUCHSIA) | 6 #if defined(HOST_OS_FUCHSIA) |
7 | 7 |
8 #include "vm/os.h" | 8 #include "vm/os.h" |
9 | 9 |
10 #include <errno.h> | 10 #include <errno.h> |
(...skipping 13 matching lines...) Expand all Loading... |
24 generate_perf_events_symbols, | 24 generate_perf_events_symbols, |
25 false, | 25 false, |
26 "Generate events symbols for profiling with perf"); | 26 "Generate events symbols for profiling with perf"); |
27 | 27 |
28 #endif // !PRODUCT | 28 #endif // !PRODUCT |
29 | 29 |
30 const char* OS::Name() { | 30 const char* OS::Name() { |
31 return "fuchsia"; | 31 return "fuchsia"; |
32 } | 32 } |
33 | 33 |
34 | |
35 intptr_t OS::ProcessId() { | 34 intptr_t OS::ProcessId() { |
36 return static_cast<intptr_t>(getpid()); | 35 return static_cast<intptr_t>(getpid()); |
37 } | 36 } |
38 | 37 |
39 | |
40 static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { | 38 static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { |
41 time_t seconds = static_cast<time_t>(seconds_since_epoch); | 39 time_t seconds = static_cast<time_t>(seconds_since_epoch); |
42 if (seconds != seconds_since_epoch) { | 40 if (seconds != seconds_since_epoch) { |
43 return false; | 41 return false; |
44 } | 42 } |
45 struct tm* error_code = localtime_r(&seconds, tm_result); | 43 struct tm* error_code = localtime_r(&seconds, tm_result); |
46 return error_code != NULL; | 44 return error_code != NULL; |
47 } | 45 } |
48 | 46 |
49 | |
50 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { | 47 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { |
51 tm decomposed; | 48 tm decomposed; |
52 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); | 49 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); |
53 // If unsuccessful, return an empty string like V8 does. | 50 // If unsuccessful, return an empty string like V8 does. |
54 return (succeeded && (decomposed.tm_zone != NULL)) ? decomposed.tm_zone : ""; | 51 return (succeeded && (decomposed.tm_zone != NULL)) ? decomposed.tm_zone : ""; |
55 } | 52 } |
56 | 53 |
57 | |
58 int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) { | 54 int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) { |
59 tm decomposed; | 55 tm decomposed; |
60 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); | 56 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); |
61 // Even if the offset was 24 hours it would still easily fit into 32 bits. | 57 // Even if the offset was 24 hours it would still easily fit into 32 bits. |
62 // If unsuccessful, return zero like V8 does. | 58 // If unsuccessful, return zero like V8 does. |
63 return succeeded ? static_cast<int>(decomposed.tm_gmtoff) : 0; | 59 return succeeded ? static_cast<int>(decomposed.tm_gmtoff) : 0; |
64 } | 60 } |
65 | 61 |
66 | |
67 int OS::GetLocalTimeZoneAdjustmentInSeconds() { | 62 int OS::GetLocalTimeZoneAdjustmentInSeconds() { |
68 // TODO(floitsch): avoid excessive calls to tzset? | 63 // TODO(floitsch): avoid excessive calls to tzset? |
69 tzset(); | 64 tzset(); |
70 // Even if the offset was 24 hours it would still easily fit into 32 bits. | 65 // Even if the offset was 24 hours it would still easily fit into 32 bits. |
71 // Note that Unix and Dart disagree on the sign. | 66 // Note that Unix and Dart disagree on the sign. |
72 return static_cast<int>(-timezone); | 67 return static_cast<int>(-timezone); |
73 } | 68 } |
74 | 69 |
75 | |
76 int64_t OS::GetCurrentTimeMillis() { | 70 int64_t OS::GetCurrentTimeMillis() { |
77 return GetCurrentTimeMicros() / 1000; | 71 return GetCurrentTimeMicros() / 1000; |
78 } | 72 } |
79 | 73 |
80 | |
81 int64_t OS::GetCurrentTimeMicros() { | 74 int64_t OS::GetCurrentTimeMicros() { |
82 return mx_time_get(MX_CLOCK_UTC) / kNanosecondsPerMicrosecond; | 75 return mx_time_get(MX_CLOCK_UTC) / kNanosecondsPerMicrosecond; |
83 } | 76 } |
84 | 77 |
85 | |
86 int64_t OS::GetCurrentMonotonicTicks() { | 78 int64_t OS::GetCurrentMonotonicTicks() { |
87 return mx_time_get(MX_CLOCK_MONOTONIC); | 79 return mx_time_get(MX_CLOCK_MONOTONIC); |
88 } | 80 } |
89 | 81 |
90 | |
91 int64_t OS::GetCurrentMonotonicFrequency() { | 82 int64_t OS::GetCurrentMonotonicFrequency() { |
92 return kNanosecondsPerSecond; | 83 return kNanosecondsPerSecond; |
93 } | 84 } |
94 | 85 |
95 | |
96 int64_t OS::GetCurrentMonotonicMicros() { | 86 int64_t OS::GetCurrentMonotonicMicros() { |
97 int64_t ticks = GetCurrentMonotonicTicks(); | 87 int64_t ticks = GetCurrentMonotonicTicks(); |
98 ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond); | 88 ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond); |
99 return ticks / kNanosecondsPerMicrosecond; | 89 return ticks / kNanosecondsPerMicrosecond; |
100 } | 90 } |
101 | 91 |
102 | |
103 int64_t OS::GetCurrentThreadCPUMicros() { | 92 int64_t OS::GetCurrentThreadCPUMicros() { |
104 return mx_time_get(MX_CLOCK_THREAD) / kNanosecondsPerMicrosecond; | 93 return mx_time_get(MX_CLOCK_THREAD) / kNanosecondsPerMicrosecond; |
105 } | 94 } |
106 | 95 |
107 | |
108 // TODO(5411554): May need to hoist these architecture dependent code | 96 // TODO(5411554): May need to hoist these architecture dependent code |
109 // into a architecture specific file e.g: os_ia32_fuchsia.cc | 97 // into a architecture specific file e.g: os_ia32_fuchsia.cc |
110 intptr_t OS::ActivationFrameAlignment() { | 98 intptr_t OS::ActivationFrameAlignment() { |
111 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ | 99 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ |
112 defined(TARGET_ARCH_ARM64) | 100 defined(TARGET_ARCH_ARM64) |
113 const int kMinimumAlignment = 16; | 101 const int kMinimumAlignment = 16; |
114 #elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_DBC) | 102 #elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_DBC) |
115 const int kMinimumAlignment = 8; | 103 const int kMinimumAlignment = 8; |
116 #else | 104 #else |
117 #error Unsupported architecture. | 105 #error Unsupported architecture. |
118 #endif | 106 #endif |
119 intptr_t alignment = kMinimumAlignment; | 107 intptr_t alignment = kMinimumAlignment; |
120 // TODO(5411554): Allow overriding default stack alignment for | 108 // TODO(5411554): Allow overriding default stack alignment for |
121 // testing purposes. | 109 // testing purposes. |
122 // Flags::DebugIsInt("stackalign", &alignment); | 110 // Flags::DebugIsInt("stackalign", &alignment); |
123 ASSERT(Utils::IsPowerOfTwo(alignment)); | 111 ASSERT(Utils::IsPowerOfTwo(alignment)); |
124 ASSERT(alignment >= kMinimumAlignment); | 112 ASSERT(alignment >= kMinimumAlignment); |
125 return alignment; | 113 return alignment; |
126 } | 114 } |
127 | 115 |
128 | |
129 intptr_t OS::PreferredCodeAlignment() { | 116 intptr_t OS::PreferredCodeAlignment() { |
130 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ | 117 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ |
131 defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC) | 118 defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC) |
132 const int kMinimumAlignment = 32; | 119 const int kMinimumAlignment = 32; |
133 #elif defined(TARGET_ARCH_ARM) | 120 #elif defined(TARGET_ARCH_ARM) |
134 const int kMinimumAlignment = 16; | 121 const int kMinimumAlignment = 16; |
135 #else | 122 #else |
136 #error Unsupported architecture. | 123 #error Unsupported architecture. |
137 #endif | 124 #endif |
138 intptr_t alignment = kMinimumAlignment; | 125 intptr_t alignment = kMinimumAlignment; |
139 // TODO(5411554): Allow overriding default code alignment for | 126 // TODO(5411554): Allow overriding default code alignment for |
140 // testing purposes. | 127 // testing purposes. |
141 // Flags::DebugIsInt("codealign", &alignment); | 128 // Flags::DebugIsInt("codealign", &alignment); |
142 ASSERT(Utils::IsPowerOfTwo(alignment)); | 129 ASSERT(Utils::IsPowerOfTwo(alignment)); |
143 ASSERT(alignment >= kMinimumAlignment); | 130 ASSERT(alignment >= kMinimumAlignment); |
144 ASSERT(alignment <= OS::kMaxPreferredCodeAlignment); | 131 ASSERT(alignment <= OS::kMaxPreferredCodeAlignment); |
145 return alignment; | 132 return alignment; |
146 } | 133 } |
147 | 134 |
148 | |
149 int OS::NumberOfAvailableProcessors() { | 135 int OS::NumberOfAvailableProcessors() { |
150 return sysconf(_SC_NPROCESSORS_CONF); | 136 return sysconf(_SC_NPROCESSORS_CONF); |
151 } | 137 } |
152 | 138 |
153 | |
154 uintptr_t OS::MaxRSS() { | 139 uintptr_t OS::MaxRSS() { |
155 mx_info_task_stats_t task_stats; | 140 mx_info_task_stats_t task_stats; |
156 mx_handle_t process = mx_process_self(); | 141 mx_handle_t process = mx_process_self(); |
157 mx_status_t status = mx_object_get_info( | 142 mx_status_t status = mx_object_get_info( |
158 process, MX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL); | 143 process, MX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL); |
159 return (status == MX_OK) | 144 return (status == MX_OK) |
160 ? (task_stats.mem_private_bytes + task_stats.mem_shared_bytes) | 145 ? (task_stats.mem_private_bytes + task_stats.mem_shared_bytes) |
161 : 0; | 146 : 0; |
162 } | 147 } |
163 | 148 |
164 | |
165 void OS::Sleep(int64_t millis) { | 149 void OS::Sleep(int64_t millis) { |
166 SleepMicros(millis * kMicrosecondsPerMillisecond); | 150 SleepMicros(millis * kMicrosecondsPerMillisecond); |
167 } | 151 } |
168 | 152 |
169 | |
170 void OS::SleepMicros(int64_t micros) { | 153 void OS::SleepMicros(int64_t micros) { |
171 mx_nanosleep(mx_deadline_after(micros * kNanosecondsPerMicrosecond)); | 154 mx_nanosleep(mx_deadline_after(micros * kNanosecondsPerMicrosecond)); |
172 } | 155 } |
173 | 156 |
174 | |
175 void OS::DebugBreak() { | 157 void OS::DebugBreak() { |
176 UNIMPLEMENTED(); | 158 UNIMPLEMENTED(); |
177 } | 159 } |
178 | 160 |
179 | |
180 uintptr_t DART_NOINLINE OS::GetProgramCounter() { | 161 uintptr_t DART_NOINLINE OS::GetProgramCounter() { |
181 return reinterpret_cast<uintptr_t>( | 162 return reinterpret_cast<uintptr_t>( |
182 __builtin_extract_return_addr(__builtin_return_address(0))); | 163 __builtin_extract_return_addr(__builtin_return_address(0))); |
183 } | 164 } |
184 | 165 |
185 | |
186 char* OS::StrNDup(const char* s, intptr_t n) { | 166 char* OS::StrNDup(const char* s, intptr_t n) { |
187 return strndup(s, n); | 167 return strndup(s, n); |
188 } | 168 } |
189 | 169 |
190 | |
191 intptr_t OS::StrNLen(const char* s, intptr_t n) { | 170 intptr_t OS::StrNLen(const char* s, intptr_t n) { |
192 return strnlen(s, n); | 171 return strnlen(s, n); |
193 } | 172 } |
194 | 173 |
195 | |
196 void OS::Print(const char* format, ...) { | 174 void OS::Print(const char* format, ...) { |
197 va_list args; | 175 va_list args; |
198 va_start(args, format); | 176 va_start(args, format); |
199 VFPrint(stdout, format, args); | 177 VFPrint(stdout, format, args); |
200 va_end(args); | 178 va_end(args); |
201 } | 179 } |
202 | 180 |
203 | |
204 void OS::VFPrint(FILE* stream, const char* format, va_list args) { | 181 void OS::VFPrint(FILE* stream, const char* format, va_list args) { |
205 vfprintf(stream, format, args); | 182 vfprintf(stream, format, args); |
206 fflush(stream); | 183 fflush(stream); |
207 } | 184 } |
208 | 185 |
209 | |
210 int OS::SNPrint(char* str, size_t size, const char* format, ...) { | 186 int OS::SNPrint(char* str, size_t size, const char* format, ...) { |
211 va_list args; | 187 va_list args; |
212 va_start(args, format); | 188 va_start(args, format); |
213 int retval = VSNPrint(str, size, format, args); | 189 int retval = VSNPrint(str, size, format, args); |
214 va_end(args); | 190 va_end(args); |
215 return retval; | 191 return retval; |
216 } | 192 } |
217 | 193 |
218 | |
219 int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) { | 194 int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) { |
220 int retval = vsnprintf(str, size, format, args); | 195 int retval = vsnprintf(str, size, format, args); |
221 if (retval < 0) { | 196 if (retval < 0) { |
222 FATAL1("Fatal error in OS::VSNPrint with format '%s'", format); | 197 FATAL1("Fatal error in OS::VSNPrint with format '%s'", format); |
223 } | 198 } |
224 return retval; | 199 return retval; |
225 } | 200 } |
226 | 201 |
227 | |
228 char* OS::SCreate(Zone* zone, const char* format, ...) { | 202 char* OS::SCreate(Zone* zone, const char* format, ...) { |
229 va_list args; | 203 va_list args; |
230 va_start(args, format); | 204 va_start(args, format); |
231 char* buffer = VSCreate(zone, format, args); | 205 char* buffer = VSCreate(zone, format, args); |
232 va_end(args); | 206 va_end(args); |
233 return buffer; | 207 return buffer; |
234 } | 208 } |
235 | 209 |
236 | |
237 char* OS::VSCreate(Zone* zone, const char* format, va_list args) { | 210 char* OS::VSCreate(Zone* zone, const char* format, va_list args) { |
238 // Measure. | 211 // Measure. |
239 va_list measure_args; | 212 va_list measure_args; |
240 va_copy(measure_args, args); | 213 va_copy(measure_args, args); |
241 intptr_t len = VSNPrint(NULL, 0, format, measure_args); | 214 intptr_t len = VSNPrint(NULL, 0, format, measure_args); |
242 va_end(measure_args); | 215 va_end(measure_args); |
243 | 216 |
244 char* buffer; | 217 char* buffer; |
245 if (zone) { | 218 if (zone) { |
246 buffer = zone->Alloc<char>(len + 1); | 219 buffer = zone->Alloc<char>(len + 1); |
247 } else { | 220 } else { |
248 buffer = reinterpret_cast<char*>(malloc(len + 1)); | 221 buffer = reinterpret_cast<char*>(malloc(len + 1)); |
249 } | 222 } |
250 ASSERT(buffer != NULL); | 223 ASSERT(buffer != NULL); |
251 | 224 |
252 // Print. | 225 // Print. |
253 va_list print_args; | 226 va_list print_args; |
254 va_copy(print_args, args); | 227 va_copy(print_args, args); |
255 VSNPrint(buffer, len + 1, format, print_args); | 228 VSNPrint(buffer, len + 1, format, print_args); |
256 va_end(print_args); | 229 va_end(print_args); |
257 return buffer; | 230 return buffer; |
258 } | 231 } |
259 | 232 |
260 | |
261 bool OS::StringToInt64(const char* str, int64_t* value) { | 233 bool OS::StringToInt64(const char* str, int64_t* value) { |
262 ASSERT(str != NULL && strlen(str) > 0 && value != NULL); | 234 ASSERT(str != NULL && strlen(str) > 0 && value != NULL); |
263 int32_t base = 10; | 235 int32_t base = 10; |
264 char* endptr; | 236 char* endptr; |
265 int i = 0; | 237 int i = 0; |
266 if (str[0] == '-') { | 238 if (str[0] == '-') { |
267 i = 1; | 239 i = 1; |
268 } | 240 } |
269 if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') && | 241 if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') && |
270 (str[i + 2] != '\0')) { | 242 (str[i + 2] != '\0')) { |
271 base = 16; | 243 base = 16; |
272 } | 244 } |
273 errno = 0; | 245 errno = 0; |
274 *value = strtoll(str, &endptr, base); | 246 *value = strtoll(str, &endptr, base); |
275 return ((errno == 0) && (endptr != str) && (*endptr == 0)); | 247 return ((errno == 0) && (endptr != str) && (*endptr == 0)); |
276 } | 248 } |
277 | 249 |
278 | |
279 void OS::RegisterCodeObservers() { | 250 void OS::RegisterCodeObservers() { |
280 #ifndef PRODUCT | 251 #ifndef PRODUCT |
281 if (FLAG_generate_perf_events_symbols) { | 252 if (FLAG_generate_perf_events_symbols) { |
282 UNIMPLEMENTED(); | 253 UNIMPLEMENTED(); |
283 } | 254 } |
284 #endif // !PRODUCT | 255 #endif // !PRODUCT |
285 } | 256 } |
286 | 257 |
287 | |
288 void OS::PrintErr(const char* format, ...) { | 258 void OS::PrintErr(const char* format, ...) { |
289 va_list args; | 259 va_list args; |
290 va_start(args, format); | 260 va_start(args, format); |
291 VFPrint(stderr, format, args); | 261 VFPrint(stderr, format, args); |
292 va_end(args); | 262 va_end(args); |
293 } | 263 } |
294 | 264 |
295 | |
296 void OS::InitOnce() { | 265 void OS::InitOnce() { |
297 // TODO(5411554): For now we check that initonce is called only once, | 266 // TODO(5411554): For now we check that initonce is called only once, |
298 // Once there is more formal mechanism to call InitOnce we can move | 267 // Once there is more formal mechanism to call InitOnce we can move |
299 // this check there. | 268 // this check there. |
300 static bool init_once_called = false; | 269 static bool init_once_called = false; |
301 ASSERT(init_once_called == false); | 270 ASSERT(init_once_called == false); |
302 init_once_called = true; | 271 init_once_called = true; |
303 } | 272 } |
304 | 273 |
305 | |
306 void OS::Shutdown() {} | 274 void OS::Shutdown() {} |
307 | 275 |
308 | |
309 void OS::Abort() { | 276 void OS::Abort() { |
310 abort(); | 277 abort(); |
311 } | 278 } |
312 | 279 |
313 | |
314 void OS::Exit(int code) { | 280 void OS::Exit(int code) { |
315 UNIMPLEMENTED(); | 281 UNIMPLEMENTED(); |
316 } | 282 } |
317 | 283 |
318 } // namespace dart | 284 } // namespace dart |
319 | 285 |
320 #endif // defined(HOST_OS_FUCHSIA) | 286 #endif // defined(HOST_OS_FUCHSIA) |
OLD | NEW |