8b68d343c7
avoid overflow. For each variable size heap object, compute the maximum number of elements and use that in the ::New functions to avoid overflow. If a bad length/size reaches a ::New function, that is a FATAL error -- the problem should have been caught earlier by the dart api or by the library code. Add "border guards" in the dart api and in library calls which cause new variable size heap objects to be allocated. We check for invalid length/size and throw explanatory error messages. Review URL: https://chromiumcodereview.appspot.com//10782016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10130 260f80e4-7a28-3924-810f-c04153c831b5
191 lines
4.2 KiB
C++
191 lines
4.2 KiB
C++
// 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 <errno.h>
|
|
#include <limits.h>
|
|
#include <mach/mach.h>
|
|
#include <mach/clock.h>
|
|
#include <mach/mach_time.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <unistd.h>
|
|
|
|
#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<time_t>(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<int>(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<int>(-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<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
|
|
}
|
|
|
|
|
|
word OS::ActivationFrameAlignment() {
|
|
// OS X activation frames must be 16 byte-aligned; see "Mac OS X ABI
|
|
// Function Call Guide".
|
|
return 16;
|
|
}
|
|
|
|
|
|
word OS::PreferredCodeAlignment() {
|
|
ASSERT(32 <= OS::kMaxPreferredCodeAlignment);
|
|
return 32;
|
|
}
|
|
|
|
|
|
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
|