tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BaseAlloc.cpp (2247B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 #include "BaseAlloc.h"
      6 
      7 #include <cstring>
      8 
      9 #include "Globals.h"
     10 
     11 using namespace mozilla;
     12 
     13 constinit BaseAlloc sBaseAlloc;
     14 
     15 // Initialize base allocation data structures.
     16 void BaseAlloc::Init() MOZ_REQUIRES(gInitLock) { mMutex.Init(); }
     17 
     18 bool BaseAlloc::pages_alloc(size_t minsize) MOZ_REQUIRES(mMutex) {
     19  MOZ_ASSERT(minsize != 0);
     20  size_t csize = CHUNK_CEILING(minsize);
     21  uintptr_t base_pages =
     22      reinterpret_cast<uintptr_t>(chunk_alloc(csize, kChunkSize, true));
     23  if (base_pages == 0) {
     24    return false;
     25  }
     26  mNextAddr = reinterpret_cast<uintptr_t>(base_pages);
     27  mPastAddr = base_pages + csize;
     28  // Leave enough pages for minsize committed, since otherwise they would
     29  // have to be immediately recommitted.
     30  size_t pminsize = REAL_PAGE_CEILING(minsize);
     31  mNextDecommitted = base_pages + pminsize;
     32  if (pminsize < csize) {
     33    pages_decommit(reinterpret_cast<void*>(mNextDecommitted), csize - pminsize);
     34  }
     35  mStats.mMapped += csize;
     36  mStats.mCommitted += pminsize;
     37 
     38  return true;
     39 }
     40 
     41 void* BaseAlloc::alloc(size_t aSize) {
     42  // Round size up to nearest multiple of the cacheline size.
     43  size_t csize = CACHELINE_CEILING(aSize);
     44 
     45  MutexAutoLock lock(mMutex);
     46  // Make sure there's enough space for the allocation.
     47  if (mNextAddr + csize > mPastAddr) {
     48    if (!pages_alloc(csize)) {
     49      return nullptr;
     50    }
     51  }
     52  // Allocate.
     53  void* ret = reinterpret_cast<void*>(mNextAddr);
     54  mNextAddr = mNextAddr + csize;
     55  // Make sure enough pages are committed for the new allocation.
     56  if (mNextAddr > mNextDecommitted) {
     57    uintptr_t pbase_next_addr = REAL_PAGE_CEILING(mNextAddr);
     58 
     59    if (!pages_commit(reinterpret_cast<void*>(mNextDecommitted),
     60                      mNextAddr - mNextDecommitted)) {
     61      return nullptr;
     62    }
     63 
     64    mStats.mCommitted += pbase_next_addr - mNextDecommitted;
     65    mNextDecommitted = pbase_next_addr;
     66  }
     67 
     68  return ret;
     69 }
     70 
     71 void* BaseAlloc::calloc(size_t aNumber, size_t aSize) {
     72  void* ret = alloc(aNumber * aSize);
     73  if (ret) {
     74    memset(ret, 0, aNumber * aSize);
     75  }
     76  return ret;
     77 }