2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/experimental/symbolizer/ElfCache.h>
19 namespace folly { namespace symbolizer {
21 SignalSafeElfCache::SignalSafeElfCache(size_t capacity) {
22 map_.reserve(capacity);
23 slots_.reserve(capacity);
26 for (size_t i = 0; i < capacity; ++i) {
27 slots_.push_back(std::make_shared<ElfFile>());
31 std::shared_ptr<ElfFile> SignalSafeElfCache::getFile(StringPiece p) {
32 if (p.size() > Path::kMaxSize) {
37 auto pos = map_.find(path);
38 if (pos != map_.end()) {
39 return slots_[pos->second];
42 size_t n = map_.size();
43 if (n >= slots_.size()) {
44 DCHECK_EQ(map_.size(), slots_.size());
51 int r = f->openNoThrow(path.data(), true, &msg);
52 if (r != ElfFile::kSuccess) {
60 ElfCache::ElfCache(size_t capacity) : capacity_(capacity) { }
62 std::shared_ptr<ElfFile> ElfCache::getFile(StringPiece p) {
63 std::lock_guard<std::mutex> lock(mutex_);
65 auto pos = files_.find(p);
66 if (pos != files_.end()) {
67 // Found, move to back (MRU)
68 auto& entry = pos->second;
69 lruList_.erase(lruList_.iterator_to(*entry));
70 lruList_.push_back(*entry);
71 return filePtr(entry);
74 auto entry = std::make_shared<Entry>();
75 entry->path = p.str();
76 auto& path = entry->path;
78 // No negative caching
80 int r = entry->file.openNoThrow(path.c_str(), true, &msg);
81 if (r != ElfFile::kSuccess) {
85 if (files_.size() == capacity_) {
86 auto& e = lruList_.front();
91 files_.emplace(entry->path, entry);
92 lruList_.push_back(*entry);
94 return filePtr(entry);
97 std::shared_ptr<ElfFile> ElfCache::filePtr(const std::shared_ptr<Entry>& e) {
99 return std::shared_ptr<ElfFile>(e, &e->file);