// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "courgette/memory_allocator.h" #include #include "base/file_util.h" #include "base/stringprintf.h" #ifdef OS_WIN // A helper function to help diagnose failures we've seen in the field. // The function constructs a string containing the error and throws a runtime // exception. The calling convention is set to stdcall to force argument // passing via the stack. __declspec(noinline) void __stdcall RuntimeError(DWORD err) { char buffer[20] = {0}; wsprintfA(buffer, "err: %u", err); throw buffer; } namespace courgette { // TempFile TempFile::TempFile() : file_(base::kInvalidPlatformFileValue), size_(0) { } TempFile::~TempFile() { Close(); } FilePath TempFile::PrepareTempFile() { FilePath path; if (!file_util::CreateTemporaryFile(&path)) RuntimeError(::GetLastError()); return path; } void TempFile::Close() { if (valid()) { base::ClosePlatformFile(file_); file_ = base::kInvalidPlatformFileValue; size_ = 0; } } void TempFile::Create() { DCHECK(file_ == base::kInvalidPlatformFileValue); FilePath path(PrepareTempFile()); bool created = false; base::PlatformFileError error_code = base::PLATFORM_FILE_OK; int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_DELETE_ON_CLOSE | base::PLATFORM_FILE_TEMPORARY; file_ = base::CreatePlatformFile(path, flags, &created, &error_code); if (file_ == base::kInvalidPlatformFileValue) RuntimeError(error_code); } bool TempFile::valid() const { return file_ != base::kInvalidPlatformFileValue; } base::PlatformFile TempFile::handle() const { return file_; } size_t TempFile::size() const { return size_; } void TempFile::SetSize(size_t size) { bool set = base::TruncatePlatformFile(file_, size); if (!set) RuntimeError(::GetLastError()); size_ = size; } // FileMapping FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { } FileMapping::~FileMapping() { Close(); } void FileMapping::InitializeView(size_t size) { DCHECK(view_ == NULL); DCHECK(mapping_ != NULL); view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); if (!view_) RuntimeError(::GetLastError()); } void FileMapping::Create(HANDLE file, size_t size) { DCHECK(file != INVALID_HANDLE_VALUE); DCHECK(!valid()); mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); if (!mapping_) RuntimeError(::GetLastError()); InitializeView(size); } void FileMapping::Close() { if (view_) ::UnmapViewOfFile(view_); if (mapping_) ::CloseHandle(mapping_); mapping_ = NULL; view_ = NULL; } bool FileMapping::valid() const { return view_ != NULL; } void* FileMapping::view() const { return view_; } // TempMapping TempMapping::TempMapping() { } TempMapping::~TempMapping() { } void TempMapping::Initialize(size_t size) { // TODO(tommi): The assumption here is that the alignment of pointers (this) // is as strict or stricter than the alignment of the element type. This is // not always true, e.g. __m128 has 16-byte alignment. size += sizeof(this); file_.Create(); file_.SetSize(size); mapping_.Create(file_.handle(), size); TempMapping** write = reinterpret_cast(mapping_.view()); write[0] = this; } void* TempMapping::memory() const { uint8* mem = reinterpret_cast(mapping_.view()); if (mem) mem += sizeof(this); DCHECK(mem); return mem; } // static TempMapping* TempMapping::GetMappingFromPtr(void* mem) { TempMapping* ret = NULL; if (mem) { ret = reinterpret_cast(mem)[-1]; } DCHECK(ret); return ret; } } // namespace courgette #endif // OS_WIN