memory_allocator.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #include "courgette/memory_allocator.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <map>
  8. #include "base/files/file_util.h"
  9. #include "build/build_config.h"
  10. #if BUILDFLAG(IS_WIN)
  11. #include <windows.h>
  12. namespace {
  13. // The file is created in the %TEMP% folder.
  14. // NOTE: Since the file will be used as backing for a memory allocation,
  15. // it will never be so big that size_t cannot represent its size.
  16. base::File CreateTempFile() {
  17. base::FilePath path;
  18. if (!base::CreateTemporaryFile(&path))
  19. return base::File();
  20. int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
  21. base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
  22. base::File::FLAG_WIN_TEMPORARY;
  23. return base::File(path, flags);
  24. }
  25. } // namespace
  26. namespace courgette {
  27. // FileMapping
  28. FileMapping::FileMapping() : mapping_(nullptr), view_(nullptr) {}
  29. FileMapping::~FileMapping() {
  30. Close();
  31. }
  32. bool FileMapping::InitializeView(size_t size) {
  33. DCHECK(view_ == nullptr);
  34. DCHECK(mapping_ != nullptr);
  35. view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size);
  36. if (!view_) {
  37. Close();
  38. return false;
  39. }
  40. return true;
  41. }
  42. bool FileMapping::Create(HANDLE file, size_t size) {
  43. DCHECK(file != INVALID_HANDLE_VALUE);
  44. DCHECK(!valid());
  45. mapping_ = ::CreateFileMapping(file, nullptr, PAGE_READWRITE, 0, 0, nullptr);
  46. if (!mapping_)
  47. return false;
  48. return InitializeView(size);
  49. }
  50. void FileMapping::Close() {
  51. if (view_)
  52. ::UnmapViewOfFile(view_);
  53. if (mapping_)
  54. ::CloseHandle(mapping_);
  55. mapping_ = nullptr;
  56. view_ = nullptr;
  57. }
  58. bool FileMapping::valid() const {
  59. return view_ != nullptr;
  60. }
  61. void* FileMapping::view() const {
  62. return view_;
  63. }
  64. // TempMapping
  65. TempMapping::TempMapping() {
  66. }
  67. TempMapping::~TempMapping() {
  68. }
  69. bool TempMapping::Initialize(size_t size) {
  70. file_ = CreateTempFile();
  71. if (!file_.IsValid())
  72. return false;
  73. // TODO(tommi): The assumption here is that the alignment of pointers (this)
  74. // is as strict or stricter than the alignment of the element type. This is
  75. // not always true, e.g. __m128 has 16-byte alignment.
  76. size += sizeof(this);
  77. if (!file_.SetLength(size) ||
  78. !mapping_.Create(file_.GetPlatformFile(), size)) {
  79. file_.Close();
  80. return false;
  81. }
  82. TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view());
  83. write[0] = this;
  84. return true;
  85. }
  86. void* TempMapping::memory() const {
  87. uint8_t* mem = reinterpret_cast<uint8_t*>(mapping_.view());
  88. // The 'this' pointer is written at the start of mapping_.view(), so
  89. // go past it. (See Initialize()).
  90. if (mem)
  91. mem += sizeof(this);
  92. DCHECK(mem);
  93. return mem;
  94. }
  95. bool TempMapping::valid() const {
  96. return mapping_.valid();
  97. }
  98. // static
  99. TempMapping* TempMapping::GetMappingFromPtr(void* mem) {
  100. TempMapping* ret = nullptr;
  101. if (mem) {
  102. ret = reinterpret_cast<TempMapping**>(mem)[-1];
  103. }
  104. DCHECK(ret);
  105. return ret;
  106. }
  107. } // namespace courgette
  108. #endif // BUILDFLAG(IS_WIN)