Home | History | Annotate | Download | only in courgette
      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