123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <err.h>
- #include <inttypes.h>
- #include <stdatomic.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <unistd.h>
- #include "err.h"
- #include "Pointers.h"
- Pointers::Pointers(size_t max_allocs) {
- size_t pagesize = getpagesize();
- // Create a mmap that contains a 4:1 ratio of allocations to entries.
- // Align to a page.
- pointers_size_ = (max_allocs * 4 * sizeof(pointer_data) + pagesize - 1) & ~(pagesize - 1);
- max_pointers_ = pointers_size_ / sizeof(pointer_data);
- void* memory = mmap(nullptr, pointers_size_, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (memory == MAP_FAILED) {
- err(1, "Unable to allocate data for pointer hash: %zu total_allocs\n", max_allocs);
- }
- // Make sure that all of the PSS for this is counted right away.
- memset(memory, 0, pointers_size_);
- pointers_ = reinterpret_cast<pointer_data*>(memory);
- }
- Pointers::~Pointers() {
- if (pointers_ != nullptr) {
- munmap(pointers_, pointers_size_);
- pointers_ = nullptr;
- }
- }
- void Pointers::Add(uintptr_t key_pointer, void* pointer) {
- pointer_data* data = FindEmpty(key_pointer);
- if (data == nullptr) {
- err(1, "No empty entry found for 0x%" PRIxPTR "\n", key_pointer);
- }
- atomic_store(&data->key_pointer, key_pointer);
- data->pointer = pointer;
- }
- void* Pointers::Remove(uintptr_t key_pointer) {
- if (key_pointer == 0) {
- err(1, "Illegal zero value passed to Remove\n");
- }
- pointer_data* data = Find(key_pointer);
- if (data == nullptr) {
- err(1, "No pointer value found for 0x%" PRIxPTR "\n", key_pointer);
- }
- void* pointer = data->pointer;
- atomic_store(&data->key_pointer, uintptr_t(0));
- return pointer;
- }
- pointer_data* Pointers::Find(uintptr_t key_pointer) {
- size_t index = GetHash(key_pointer);
- for (size_t entries = max_pointers_; entries != 0; entries--) {
- if (atomic_load(&pointers_[index].key_pointer) == key_pointer) {
- return pointers_ + index;
- }
- if (++index == max_pointers_) {
- index = 0;
- }
- }
- return nullptr;
- }
- pointer_data* Pointers::FindEmpty(uintptr_t key_pointer) {
- size_t index = GetHash(key_pointer);
- for (size_t entries = 0; entries < max_pointers_; entries++) {
- uintptr_t empty = 0;
- if (atomic_compare_exchange_strong(&pointers_[index].key_pointer, &empty,
- uintptr_t(1))) {
- return pointers_ + index;
- }
- if (++index == max_pointers_) {
- index = 0;
- }
- }
- return nullptr;
- }
- size_t Pointers::GetHash(uintptr_t key_pointer) {
- return key_pointer % max_pointers_;
- }
- void Pointers::FreeAll() {
- for (size_t i = 0; i < max_pointers_; i++) {
- if (atomic_load(&pointers_[i].key_pointer) != 0) {
- free(pointers_[i].pointer);
- }
- }
- }
|