// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/os.h" #include #include #include #include #include #include #include #include "platform/utils.h" #include "vm/isolate.h" namespace dart { static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { time_t seconds = static_cast(seconds_since_epoch); if (seconds != seconds_since_epoch) return false; struct tm* error_code = localtime_r(&seconds, tm_result); return error_code != NULL; } const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { tm decomposed; bool succeeded = LocalTime(seconds_since_epoch, &decomposed); ASSERT(succeeded); return decomposed.tm_zone; } int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) { tm decomposed; bool succeeded = LocalTime(seconds_since_epoch, &decomposed); ASSERT(succeeded); // Even if the offset was 24 hours it would still easily fit into 32 bits. return static_cast(decomposed.tm_gmtoff); } int OS::GetLocalTimeZoneAdjustmentInSeconds() { // TODO(floitsch): avoid excessive calls to tzset? tzset(); // Even if the offset was 24 hours it would still easily fit into 32 bits. // Note that Unix and Dart disagree on the sign. return static_cast(-timezone); } int64_t OS::GetCurrentTimeMillis() { return GetCurrentTimeMicros() / 1000; } int64_t OS::GetCurrentTimeMicros() { // gettimeofday has microsecond resolution. struct timeval tv; if (gettimeofday(&tv, NULL) < 0) { UNREACHABLE(); return 0; } return (static_cast(tv.tv_sec) * 1000000) + tv.tv_usec; } // TODO(5411554): May need to hoist these architecture dependent code // into a architecture specific file e.g: os_ia32_linux.cc word OS::ActivationFrameAlignment() { #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) const int kMinimumAlignment = 16; #elif defined(TARGET_ARCH_ARM) const int kMinimumAlignment = 8; #else #error Unsupported architecture. #endif word alignment = kMinimumAlignment; // TODO(5411554): Allow overriding default stack alignment for // testing purposes. // Flags::DebugIsInt("stackalign", &alignment); ASSERT(Utils::IsPowerOfTwo(alignment)); ASSERT(alignment >= kMinimumAlignment); return alignment; } word OS::PreferredCodeAlignment() { #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) const int kMinimumAlignment = 16; #elif defined(TARGET_ARCH_ARM) const int kMinimumAlignment = 16; #else #error Unsupported architecture. #endif word alignment = kMinimumAlignment; // TODO(5411554): Allow overriding default code alignment for // testing purposes. // Flags::DebugIsInt("codealign", &alignment); ASSERT(Utils::IsPowerOfTwo(alignment)); ASSERT(alignment >= kMinimumAlignment); ASSERT(alignment <= OS::kMaxPreferredCodeAlignment); return alignment; } uword OS::GetStackSizeLimit() { struct rlimit stack_limit; int retval = getrlimit(RLIMIT_STACK, &stack_limit); ASSERT(retval == 0); if (stack_limit.rlim_cur > INT_MAX) { retval = INT_MAX; } else { retval = stack_limit.rlim_cur; } return retval; } int OS::NumberOfAvailableProcessors() { return sysconf(_SC_NPROCESSORS_ONLN); } void OS::Sleep(int64_t millis) { // TODO(5411554): For now just use usleep we may have to revisit this. usleep(millis * 1000); } void OS::Print(const char* format, ...) { va_list args; va_start(args, format); VFPrint(stdout, format, args); va_end(args); } void OS::VFPrint(FILE* stream, const char* format, va_list args) { vfprintf(stream, format, args); fflush(stream); } int OS::SNPrint(char* str, size_t size, const char* format, ...) { va_list args; va_start(args, format); int retval = VSNPrint(str, size, format, args); va_end(args); return retval; } int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) { int retval = vsnprintf(str, size, format, args); if (retval < 0) { FATAL1("Fatal error in OS::VSNPrint with format '%s'", format); } return retval; } bool OS::StringToInt64(const char* str, int64_t* value) { ASSERT(str != NULL && strlen(str) > 0 && value != NULL); int32_t base = 10; char* endptr; int i = 0; if (str[0] == '-') { i = 1; } if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') && (str[i + 2] != '\0')) { base = 16; } errno = 0; *value = strtoll(str, &endptr, base); return ((errno == 0) && (endptr != str) && (*endptr == 0)); } void OS::PrintErr(const char* format, ...) { va_list args; va_start(args, format); VFPrint(stderr, format, args); va_end(args); } void OS::InitOnce() { // TODO(5411554): For now we check that initonce is called only once, // Once there is more formal mechanism to call InitOnce we can move // this check there. static bool init_once_called = false; ASSERT(init_once_called == false); init_once_called = true; } void OS::Shutdown() { } void OS::Abort() { abort(); } void OS::Exit(int code) { exit(code); } } // namespace dart