1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 9 #include "base/file_util.h" 10 #include "base/strings/stringprintf.h" 11 12 #if defined(OS_WIN) 13 14 namespace { 15 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() { 20 base::FilePath path; 21 if (!base::CreateTemporaryFile(&path)) 22 return base::File(); 23 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); 28 } 29 30 } // namespace 31 32 namespace courgette { 33 34 // FileMapping 35 36 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { 37 } 38 39 FileMapping::~FileMapping() { 40 Close(); 41 } 42 43 bool FileMapping::InitializeView(size_t size) { 44 DCHECK(view_ == NULL); 45 DCHECK(mapping_ != NULL); 46 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size); 47 if (!view_) { 48 Close(); 49 return false; 50 } 51 return true; 52 } 53 54 bool FileMapping::Create(HANDLE file, size_t size) { 55 DCHECK(file != INVALID_HANDLE_VALUE); 56 DCHECK(!valid()); 57 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL); 58 if (!mapping_) 59 return false; 60 61 return InitializeView(size); 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 89 bool TempMapping::Initialize(size_t size) { 90 file_ = CreateTempFile(); 91 if (!file_.IsValid()) 92 return false; 93 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); 98 if (!file_.SetLength(size) || 99 !mapping_.Create(file_.GetPlatformFile(), size)) { 100 file_.Close(); 101 return false; 102 } 103 104 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view()); 105 write[0] = this; 106 107 return true; 108 } 109 110 void* TempMapping::memory() const { 111 uint8* mem = reinterpret_cast<uint8*>(mapping_.view()); 112 // The 'this' pointer is written at the start of mapping_.view(), so 113 // go past it. (See Initialize()). 114 if (mem) 115 mem += sizeof(this); 116 DCHECK(mem); 117 return mem; 118 } 119 120 bool TempMapping::valid() const { 121 return mapping_.valid(); 122 } 123 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 137