| // 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 <map> |
| |
| #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<TempMapping**>(mapping_.view()); |
| write[0] = this; |
| } |
| |
| void* TempMapping::memory() const { |
| uint8* mem = reinterpret_cast<uint8*>(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<TempMapping**>(mem)[-1]; |
| } |
| DCHECK(ret); |
| return ret; |
| } |
| |
| } // namespace courgette |
| |
| #endif // OS_WIN |