[email protected] | 5ace0a8 | 2012-07-25 21:26:12 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "courgette/memory_allocator.h" |
| 6 | |
| 7 | #include <map> |
| 8 | |
thestig | c9e38a2 | 2014-09-13 01:02:11 | [diff] [blame] | 9 | #include "base/files/file_util.h" |
[email protected] | 68c986e | 2013-06-11 13:26:25 | [diff] [blame] | 10 | #include "base/strings/stringprintf.h" |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 11 | |
[email protected] | 3166220 | 2013-03-23 19:10:54 | [diff] [blame] | 12 | #if defined(OS_WIN) |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 13 | |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 14 | namespace { |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 15 | |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 16 | // The file is created in the %TEMP% folder. |
| 17 | // NOTE: Since the file will be used as backing for a memory allocation, |
| 18 | // it will never be so big that size_t cannot represent its size. |
| 19 | base::File CreateTempFile() { |
[email protected] | 9e27571 | 2013-02-10 19:20:14 | [diff] [blame] | 20 | base::FilePath path; |
[email protected] | 03d9afc0 | 2013-12-03 17:55:52 | [diff] [blame] | 21 | if (!base::CreateTemporaryFile(&path)) |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 22 | return base::File(); |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 23 | |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 24 | int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | |
| 25 | base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE | |
| 26 | base::File::FLAG_TEMPORARY; |
| 27 | return base::File(path, flags); |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 28 | } |
| 29 | |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 30 | } // namespace |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 31 | |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 32 | namespace courgette { |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 33 | |
| 34 | // FileMapping |
| 35 | |
| 36 | FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { |
| 37 | } |
| 38 | |
| 39 | FileMapping::~FileMapping() { |
| 40 | Close(); |
| 41 | } |
| 42 | |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 43 | bool FileMapping::InitializeView(size_t size) { |
[email protected] | 6c13195 | 2011-03-03 23:39:32 | [diff] [blame] | 44 | DCHECK(view_ == NULL); |
| 45 | DCHECK(mapping_ != NULL); |
| 46 | view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 47 | if (!view_) { |
| 48 | Close(); |
| 49 | return false; |
| 50 | } |
| 51 | return true; |
[email protected] | 6c13195 | 2011-03-03 23:39:32 | [diff] [blame] | 52 | } |
| 53 | |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 54 | bool FileMapping::Create(HANDLE file, size_t size) { |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 55 | DCHECK(file != INVALID_HANDLE_VALUE); |
| 56 | DCHECK(!valid()); |
| 57 | mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); |
[email protected] | 6c13195 | 2011-03-03 23:39:32 | [diff] [blame] | 58 | if (!mapping_) |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 59 | return false; |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 60 | |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 61 | return InitializeView(size); |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | void FileMapping::Close() { |
| 65 | if (view_) |
| 66 | ::UnmapViewOfFile(view_); |
| 67 | if (mapping_) |
| 68 | ::CloseHandle(mapping_); |
| 69 | mapping_ = NULL; |
| 70 | view_ = NULL; |
| 71 | } |
| 72 | |
| 73 | bool FileMapping::valid() const { |
| 74 | return view_ != NULL; |
| 75 | } |
| 76 | |
| 77 | void* FileMapping::view() const { |
| 78 | return view_; |
| 79 | } |
| 80 | |
| 81 | // TempMapping |
| 82 | |
| 83 | TempMapping::TempMapping() { |
| 84 | } |
| 85 | |
| 86 | TempMapping::~TempMapping() { |
| 87 | } |
| 88 | |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 89 | bool TempMapping::Initialize(size_t size) { |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 90 | file_ = CreateTempFile(); |
| 91 | if (!file_.IsValid()) |
| 92 | return false; |
| 93 | |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 94 | // TODO(tommi): The assumption here is that the alignment of pointers (this) |
| 95 | // is as strict or stricter than the alignment of the element type. This is |
| 96 | // not always true, e.g. __m128 has 16-byte alignment. |
| 97 | size += sizeof(this); |
[email protected] | 578d5dae | 2014-02-21 16:07:52 | [diff] [blame] | 98 | if (!file_.SetLength(size) || |
| 99 | !mapping_.Create(file_.GetPlatformFile(), size)) { |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 100 | file_.Close(); |
| 101 | return false; |
| 102 | } |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 103 | |
[email protected] | 6c13195 | 2011-03-03 23:39:32 | [diff] [blame] | 104 | TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); |
| 105 | write[0] = this; |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 106 | |
| 107 | return true; |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 108 | } |
| 109 | |
| 110 | void* TempMapping::memory() const { |
| 111 | uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); |
[email protected] | 5ace0a8 | 2012-07-25 21:26:12 | [diff] [blame] | 112 | // The 'this' pointer is written at the start of mapping_.view(), so |
| 113 | // go past it. (See Initialize()). |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 114 | if (mem) |
| 115 | mem += sizeof(this); |
| 116 | DCHECK(mem); |
| 117 | return mem; |
| 118 | } |
| 119 | |
[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 120 | bool TempMapping::valid() const { |
| 121 | return mapping_.valid(); |
| 122 | } |
| 123 | |
[email protected] | fbd31eb | 2011-03-01 00:19:02 | [diff] [blame] | 124 | // static |
| 125 | TempMapping* TempMapping::GetMappingFromPtr(void* mem) { |
| 126 | TempMapping* ret = NULL; |
| 127 | if (mem) { |
| 128 | ret = reinterpret_cast<TempMapping**>(mem)[-1]; |
| 129 | } |
| 130 | DCHECK(ret); |
| 131 | return ret; |
| 132 | } |
| 133 | |
| 134 | } // namespace courgette |
| 135 | |
| 136 | #endif // OS_WIN |