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 14namespace { 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. 19base::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 32namespace courgette { 33 34// FileMapping 35 36FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { 37} 38 39FileMapping::~FileMapping() { 40 Close(); 41} 42 43bool 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 54bool 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 64void FileMapping::Close() { 65 if (view_) 66 ::UnmapViewOfFile(view_); 67 if (mapping_) 68 ::CloseHandle(mapping_); 69 mapping_ = NULL; 70 view_ = NULL; 71} 72 73bool FileMapping::valid() const { 74 return view_ != NULL; 75} 76 77void* FileMapping::view() const { 78 return view_; 79} 80 81// TempMapping 82 83TempMapping::TempMapping() { 84} 85 86TempMapping::~TempMapping() { 87} 88 89bool 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 110void* 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 120bool TempMapping::valid() const { 121 return mapping_.valid(); 122} 123 124// static 125TempMapping* 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