| 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. | 14 namespace courgette { |
| 15 // The function constructs a string containing the error and throws a runtime | 15 |
| 16 // exception. The calling convention is set to stdcall to force argument | |
| 17 // passing via the stack. | |
| 18 __declspec(noinline) | 16 __declspec(noinline) |
| 19 void __stdcall RuntimeError(DWORD err) { | 17 void __stdcall ThrowExceptionOnAllocationFailure(uint32 err) { |
| 20 char buffer[20] = {0}; | 18 char buffer[20] = {0}; |
| 21 wsprintfA(buffer, "err: %u", err); | 19 wsprintfA(buffer, "err: %u", err); |
| 22 throw buffer; | 20 throw buffer; |
| 23 } | 21 } |
| 24 | 22 |
| 25 namespace courgette { | |
| 26 | |
| 27 // TempFile | 23 // TempFile |
| 28 | 24 |
| 29 TempFile::TempFile() : file_(base::kInvalidPlatformFileValue), size_(0) { | 25 TempFile::TempFile() : file_(base::kInvalidPlatformFileValue), size_(0) { |
| 30 } | 26 } |
| 31 | 27 |
| 32 TempFile::~TempFile() { | 28 TempFile::~TempFile() { |
| 33 Close(); | 29 Close(); |
| 34 } | 30 } |
| 35 | 31 |
| 36 FilePath TempFile::PrepareTempFile() { | 32 bool TempFile::PrepareTempFile(FilePath* path, |
| 37 FilePath path; | 33 AllocationFailureHandler failure_handler) { |
| 38 if (!file_util::CreateTemporaryFile(&path)) | 34 if (!file_util::CreateTemporaryFile(path)) { |
| 39 RuntimeError(::GetLastError()); | 35 if (failure_handler) |
| 40 return path; | 36 failure_handler(::GetLastError()); |
| 37 return false; |
| 38 } |
| 39 return true; |
| 41 } | 40 } |
| 42 | 41 |
| 43 void TempFile::Close() { | 42 void TempFile::Close() { |
| 44 if (valid()) { | 43 if (valid()) { |
| 45 base::ClosePlatformFile(file_); | 44 base::ClosePlatformFile(file_); |
| 46 file_ = base::kInvalidPlatformFileValue; | 45 file_ = base::kInvalidPlatformFileValue; |
| 47 size_ = 0; | 46 size_ = 0; |
| 48 } | 47 } |
| 49 } | 48 } |
| 50 | 49 |
| 51 void TempFile::Create() { | 50 bool TempFile::Create(AllocationFailureHandler failure_handler) { |
| 52 DCHECK(file_ == base::kInvalidPlatformFileValue); | 51 DCHECK(file_ == base::kInvalidPlatformFileValue); |
| 53 FilePath path(PrepareTempFile()); | 52 FilePath path; |
| 53 if (!PrepareTempFile(&path, failure_handler)) |
| 54 return false; |
| 55 |
| 54 bool created = false; | 56 bool created = false; |
| 55 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; | 57 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| 56 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | | 58 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | |
| 57 base::PLATFORM_FILE_WRITE | | 59 base::PLATFORM_FILE_WRITE | |
| 58 base::PLATFORM_FILE_DELETE_ON_CLOSE | | 60 base::PLATFORM_FILE_DELETE_ON_CLOSE | |
| 59 base::PLATFORM_FILE_TEMPORARY; | 61 base::PLATFORM_FILE_TEMPORARY; |
| 60 file_ = base::CreatePlatformFile(path, flags, &created, &error_code); | 62 file_ = base::CreatePlatformFile(path, flags, &created, &error_code); |
| 61 if (file_ == base::kInvalidPlatformFileValue) | 63 if (file_ == base::kInvalidPlatformFileValue) { |
| 62 RuntimeError(error_code); | 64 if (failure_handler) |
| 65 failure_handler(error_code); |
| 66 return false; |
| 67 } |
| 68 |
| 69 return true; |
| 63 } | 70 } |
| 64 | 71 |
| 65 bool TempFile::valid() const { | 72 bool TempFile::valid() const { |
| 66 return file_ != base::kInvalidPlatformFileValue; | 73 return file_ != base::kInvalidPlatformFileValue; |
| 67 } | 74 } |
| 68 | 75 |
| 69 base::PlatformFile TempFile::handle() const { | 76 base::PlatformFile TempFile::handle() const { |
| 70 return file_; | 77 return file_; |
| 71 } | 78 } |
| 72 | 79 |
| 73 size_t TempFile::size() const { | 80 size_t TempFile::size() const { |
| 74 return size_; | 81 return size_; |
| 75 } | 82 } |
| 76 | 83 |
| 77 void TempFile::SetSize(size_t size) { | 84 bool TempFile::SetSize(size_t size, AllocationFailureHandler failure_handler) { |
| 78 bool set = base::TruncatePlatformFile(file_, size); | 85 bool set = base::TruncatePlatformFile(file_, size); |
| 79 if (!set) | 86 if (!set) { |
| 80 RuntimeError(::GetLastError()); | 87 if (failure_handler) |
| 81 size_ = size; | 88 failure_handler(::GetLastError()); |
| 89 } else { |
| 90 size_ = size; |
| 91 } |
| 92 return set; |
| 82 } | 93 } |
| 83 | 94 |
| 84 // FileMapping | 95 // FileMapping |
| 85 | 96 |
| 86 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { | 97 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { |
| 87 } | 98 } |
| 88 | 99 |
| 89 FileMapping::~FileMapping() { | 100 FileMapping::~FileMapping() { |
| 90 Close(); | 101 Close(); |
| 91 } | 102 } |
| 92 | 103 |
| 93 void FileMapping::InitializeView(size_t size) { | 104 bool FileMapping::InitializeView(size_t size, |
| 105 AllocationFailureHandler failure_handler) { |
| 94 DCHECK(view_ == NULL); | 106 DCHECK(view_ == NULL); |
| 95 DCHECK(mapping_ != NULL); | 107 DCHECK(mapping_ != NULL); |
| 96 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); | 108 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); |
| 97 if (!view_) | 109 if (!view_) { |
| 98 RuntimeError(::GetLastError()); | 110 if (failure_handler) |
| 111 failure_handler(::GetLastError()); |
| 112 Close(); |
| 113 return false; |
| 114 } |
| 115 return true; |
| 99 } | 116 } |
| 100 | 117 |
| 101 void FileMapping::Create(HANDLE file, size_t size) { | 118 bool FileMapping::Create(HANDLE file, size_t size, |
| 119 AllocationFailureHandler failure_handler) { |
| 102 DCHECK(file != INVALID_HANDLE_VALUE); | 120 DCHECK(file != INVALID_HANDLE_VALUE); |
| 103 DCHECK(!valid()); | 121 DCHECK(!valid()); |
| 104 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); | 122 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); |
| 105 if (!mapping_) | 123 if (!mapping_) { |
| 106 RuntimeError(::GetLastError()); | 124 if (failure_handler) |
| 125 failure_handler(::GetLastError()); |
| 126 return false; |
| 127 } |
| 107 | 128 |
| 108 InitializeView(size); | 129 return InitializeView(size, failure_handler); |
| 109 } | 130 } |
| 110 | 131 |
| 111 void FileMapping::Close() { | 132 void FileMapping::Close() { |
| 112 if (view_) | 133 if (view_) |
| 113 ::UnmapViewOfFile(view_); | 134 ::UnmapViewOfFile(view_); |
| 114 if (mapping_) | 135 if (mapping_) |
| 115 ::CloseHandle(mapping_); | 136 ::CloseHandle(mapping_); |
| 116 mapping_ = NULL; | 137 mapping_ = NULL; |
| 117 view_ = NULL; | 138 view_ = NULL; |
| 118 } | 139 } |
| 119 | 140 |
| 120 bool FileMapping::valid() const { | 141 bool FileMapping::valid() const { |
| 121 return view_ != NULL; | 142 return view_ != NULL; |
| 122 } | 143 } |
| 123 | 144 |
| 124 void* FileMapping::view() const { | 145 void* FileMapping::view() const { |
| 125 return view_; | 146 return view_; |
| 126 } | 147 } |
| 127 | 148 |
| 128 // TempMapping | 149 // TempMapping |
| 129 | 150 |
| 130 TempMapping::TempMapping() { | 151 TempMapping::TempMapping() { |
| 131 } | 152 } |
| 132 | 153 |
| 133 TempMapping::~TempMapping() { | 154 TempMapping::~TempMapping() { |
| 134 } | 155 } |
| 135 | 156 |
| 136 void TempMapping::Initialize(size_t size) { | 157 bool TempMapping::Initialize(size_t size, |
| 158 AllocationFailureHandler failure_handler) { |
| 137 // TODO(tommi): The assumption here is that the alignment of pointers (this) | 159 // 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 | 160 // 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. | 161 // not always true, e.g. __m128 has 16-byte alignment. |
| 140 size += sizeof(this); | 162 size += sizeof(this); |
| 141 file_.Create(); | 163 if (!file_.Create(failure_handler) || |
| 142 file_.SetSize(size); | 164 !file_.SetSize(size, failure_handler) || |
| 143 mapping_.Create(file_.handle(), size); | 165 !mapping_.Create(file_.handle(), size, failure_handler)) { |
| 166 file_.Close(); |
| 167 return false; |
| 168 } |
| 144 | 169 |
| 145 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); | 170 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); |
| 146 write[0] = this; | 171 write[0] = this; |
| 172 |
| 173 return true; |
| 147 } | 174 } |
| 148 | 175 |
| 149 void* TempMapping::memory() const { | 176 void* TempMapping::memory() const { |
| 150 uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); | 177 uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); |
| 151 if (mem) | 178 if (mem) |
| 152 mem += sizeof(this); | 179 mem += sizeof(this); |
| 153 DCHECK(mem); | 180 DCHECK(mem); |
| 154 return mem; | 181 return mem; |
| 155 } | 182 } |
| 156 | 183 |
| 184 bool TempMapping::valid() const { |
| 185 return mapping_.valid(); |
| 186 } |
| 187 |
| 157 // static | 188 // static |
| 158 TempMapping* TempMapping::GetMappingFromPtr(void* mem) { | 189 TempMapping* TempMapping::GetMappingFromPtr(void* mem) { |
| 159 TempMapping* ret = NULL; | 190 TempMapping* ret = NULL; |
| 160 if (mem) { | 191 if (mem) { |
| 161 ret = reinterpret_cast<TempMapping**>(mem)[-1]; | 192 ret = reinterpret_cast<TempMapping**>(mem)[-1]; |
| 162 } | 193 } |
| 163 DCHECK(ret); | 194 DCHECK(ret); |
| 164 return ret; | 195 return ret; |
| 165 } | 196 } |
| 166 | 197 |
| 167 } // namespace courgette | 198 } // namespace courgette |
| 168 | 199 |
| 169 #endif // OS_WIN | 200 #endif // OS_WIN |
| OLD | NEW |