| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "courgette/memory_allocator.h" | 5 #include "courgette/memory_allocator.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 | 11 |
| 12 #ifdef OS_WIN | 12 #ifdef OS_WIN |
| 13 | 13 |
| 14 // A helper function to help diagnose failures we've seen in the field. | |
| 15 // The function constructs a string containing the error and throws a runtime | |
| 16 // exception. The calling convention is set to stdcall to force argument | |
| 17 // passing via the stack. | |
| 18 __declspec(noinline) | |
| 19 void __stdcall RuntimeError(DWORD err) { | |
| 20 char buffer[20] = {0}; | |
| 21 wsprintfA(buffer, "err: %u", err); | |
| 22 throw buffer; | |
| 23 } | |
| 24 | |
| 25 namespace courgette { | 14 namespace courgette { |
| 26 | 15 |
| 27 // TempFile | 16 // TempFile |
| 28 | 17 |
| 29 TempFile::TempFile() : file_(base::kInvalidPlatformFileValue), size_(0) { | 18 TempFile::TempFile() : file_(base::kInvalidPlatformFileValue) { |
| 30 } | 19 } |
| 31 | 20 |
| 32 TempFile::~TempFile() { | 21 TempFile::~TempFile() { |
| 33 Close(); | 22 Close(); |
| 34 } | 23 } |
| 35 | 24 |
| 36 FilePath TempFile::PrepareTempFile() { | |
| 37 FilePath path; | |
| 38 if (!file_util::CreateTemporaryFile(&path)) | |
| 39 RuntimeError(::GetLastError()); | |
| 40 return path; | |
| 41 } | |
| 42 | |
| 43 void TempFile::Close() { | 25 void TempFile::Close() { |
| 44 if (valid()) { | 26 if (valid()) { |
| 45 base::ClosePlatformFile(file_); | 27 base::ClosePlatformFile(file_); |
| 46 file_ = base::kInvalidPlatformFileValue; | 28 file_ = base::kInvalidPlatformFileValue; |
| 47 size_ = 0; | |
| 48 } | 29 } |
| 49 } | 30 } |
| 50 | 31 |
| 51 void TempFile::Create() { | 32 bool TempFile::Create() { |
| 52 DCHECK(file_ == base::kInvalidPlatformFileValue); | 33 DCHECK(file_ == base::kInvalidPlatformFileValue); |
| 53 FilePath path(PrepareTempFile()); | 34 FilePath path; |
| 35 if (!file_util::CreateTemporaryFile(&path)) |
| 36 return false; |
| 37 |
| 54 bool created = false; | 38 bool created = false; |
| 55 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; | 39 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| 56 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | | 40 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | |
| 57 base::PLATFORM_FILE_WRITE | | 41 base::PLATFORM_FILE_WRITE | |
| 58 base::PLATFORM_FILE_DELETE_ON_CLOSE | | 42 base::PLATFORM_FILE_DELETE_ON_CLOSE | |
| 59 base::PLATFORM_FILE_TEMPORARY; | 43 base::PLATFORM_FILE_TEMPORARY; |
| 60 file_ = base::CreatePlatformFile(path, flags, &created, &error_code); | 44 file_ = base::CreatePlatformFile(path, flags, &created, &error_code); |
| 61 if (file_ == base::kInvalidPlatformFileValue) | 45 if (file_ == base::kInvalidPlatformFileValue) |
| 62 RuntimeError(error_code); | 46 return false; |
| 47 |
| 48 return true; |
| 63 } | 49 } |
| 64 | 50 |
| 65 bool TempFile::valid() const { | 51 bool TempFile::valid() const { |
| 66 return file_ != base::kInvalidPlatformFileValue; | 52 return file_ != base::kInvalidPlatformFileValue; |
| 67 } | 53 } |
| 68 | 54 |
| 69 base::PlatformFile TempFile::handle() const { | 55 base::PlatformFile TempFile::handle() const { |
| 70 return file_; | 56 return file_; |
| 71 } | 57 } |
| 72 | 58 |
| 73 size_t TempFile::size() const { | 59 bool TempFile::SetSize(size_t size) { |
| 74 return size_; | 60 return base::TruncatePlatformFile(file_, size); |
| 75 } | |
| 76 | |
| 77 void TempFile::SetSize(size_t size) { | |
| 78 bool set = base::TruncatePlatformFile(file_, size); | |
| 79 if (!set) | |
| 80 RuntimeError(::GetLastError()); | |
| 81 size_ = size; | |
| 82 } | 61 } |
| 83 | 62 |
| 84 // FileMapping | 63 // FileMapping |
| 85 | 64 |
| 86 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { | 65 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { |
| 87 } | 66 } |
| 88 | 67 |
| 89 FileMapping::~FileMapping() { | 68 FileMapping::~FileMapping() { |
| 90 Close(); | 69 Close(); |
| 91 } | 70 } |
| 92 | 71 |
| 93 void FileMapping::InitializeView(size_t size) { | 72 bool FileMapping::InitializeView(size_t size) { |
| 94 DCHECK(view_ == NULL); | 73 DCHECK(view_ == NULL); |
| 95 DCHECK(mapping_ != NULL); | 74 DCHECK(mapping_ != NULL); |
| 96 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); | 75 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); |
| 97 if (!view_) | 76 if (!view_) { |
| 98 RuntimeError(::GetLastError()); | 77 Close(); |
| 78 return false; |
| 79 } |
| 80 return true; |
| 99 } | 81 } |
| 100 | 82 |
| 101 void FileMapping::Create(HANDLE file, size_t size) { | 83 bool FileMapping::Create(HANDLE file, size_t size) { |
| 102 DCHECK(file != INVALID_HANDLE_VALUE); | 84 DCHECK(file != INVALID_HANDLE_VALUE); |
| 103 DCHECK(!valid()); | 85 DCHECK(!valid()); |
| 104 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); | 86 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); |
| 105 if (!mapping_) | 87 if (!mapping_) |
| 106 RuntimeError(::GetLastError()); | 88 return false; |
| 107 | 89 |
| 108 InitializeView(size); | 90 return InitializeView(size); |
| 109 } | 91 } |
| 110 | 92 |
| 111 void FileMapping::Close() { | 93 void FileMapping::Close() { |
| 112 if (view_) | 94 if (view_) |
| 113 ::UnmapViewOfFile(view_); | 95 ::UnmapViewOfFile(view_); |
| 114 if (mapping_) | 96 if (mapping_) |
| 115 ::CloseHandle(mapping_); | 97 ::CloseHandle(mapping_); |
| 116 mapping_ = NULL; | 98 mapping_ = NULL; |
| 117 view_ = NULL; | 99 view_ = NULL; |
| 118 } | 100 } |
| 119 | 101 |
| 120 bool FileMapping::valid() const { | 102 bool FileMapping::valid() const { |
| 121 return view_ != NULL; | 103 return view_ != NULL; |
| 122 } | 104 } |
| 123 | 105 |
| 124 void* FileMapping::view() const { | 106 void* FileMapping::view() const { |
| 125 return view_; | 107 return view_; |
| 126 } | 108 } |
| 127 | 109 |
| 128 // TempMapping | 110 // TempMapping |
| 129 | 111 |
| 130 TempMapping::TempMapping() { | 112 TempMapping::TempMapping() { |
| 131 } | 113 } |
| 132 | 114 |
| 133 TempMapping::~TempMapping() { | 115 TempMapping::~TempMapping() { |
| 134 } | 116 } |
| 135 | 117 |
| 136 void TempMapping::Initialize(size_t size) { | 118 bool TempMapping::Initialize(size_t size) { |
| 137 // TODO(tommi): The assumption here is that the alignment of pointers (this) | 119 // TODO(tommi): The assumption here is that the alignment of pointers (this) |
| 138 // is as strict or stricter than the alignment of the element type. This is | 120 // is as strict or stricter than the alignment of the element type. This is |
| 139 // not always true, e.g. __m128 has 16-byte alignment. | 121 // not always true, e.g. __m128 has 16-byte alignment. |
| 140 size += sizeof(this); | 122 size += sizeof(this); |
| 141 file_.Create(); | 123 if (!file_.Create() || |
| 142 file_.SetSize(size); | 124 !file_.SetSize(size) || |
| 143 mapping_.Create(file_.handle(), size); | 125 !mapping_.Create(file_.handle(), size)) { |
| 126 file_.Close(); |
| 127 return false; |
| 128 } |
| 144 | 129 |
| 145 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); | 130 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); |
| 146 write[0] = this; | 131 write[0] = this; |
| 132 |
| 133 return true; |
| 147 } | 134 } |
| 148 | 135 |
| 149 void* TempMapping::memory() const { | 136 void* TempMapping::memory() const { |
| 150 uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); | 137 uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); |
| 151 if (mem) | 138 if (mem) |
| 152 mem += sizeof(this); | 139 mem += sizeof(this); |
| 153 DCHECK(mem); | 140 DCHECK(mem); |
| 154 return mem; | 141 return mem; |
| 155 } | 142 } |
| 156 | 143 |
| 144 bool TempMapping::valid() const { |
| 145 return mapping_.valid(); |
| 146 } |
| 147 |
| 157 // static | 148 // static |
| 158 TempMapping* TempMapping::GetMappingFromPtr(void* mem) { | 149 TempMapping* TempMapping::GetMappingFromPtr(void* mem) { |
| 159 TempMapping* ret = NULL; | 150 TempMapping* ret = NULL; |
| 160 if (mem) { | 151 if (mem) { |
| 161 ret = reinterpret_cast<TempMapping**>(mem)[-1]; | 152 ret = reinterpret_cast<TempMapping**>(mem)[-1]; |
| 162 } | 153 } |
| 163 DCHECK(ret); | 154 DCHECK(ret); |
| 164 return ret; | 155 return ret; |
| 165 } | 156 } |
| 166 | 157 |
| 167 } // namespace courgette | 158 } // namespace courgette |
| 168 | 159 |
| 169 #endif // OS_WIN | 160 #endif // OS_WIN |
| OLD | NEW |