| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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 "tscore/ink_assert.h" |
| #include "tscore/ink_atomic.h" |
| #include "tscore/ink_resource.h" |
| #include <execinfo.h> |
| |
| int res_track_memory = 0; // Disabled by default |
| uint64_t ssl_memory_allocated = 0; |
| uint64_t ssl_memory_freed = 0; |
| |
| std::map<const char *, Resource *> ResourceTracker::_resourceMap; |
| ink_mutex ResourceTracker::resourceLock = PTHREAD_MUTEX_INITIALIZER; |
| |
| /** |
| * Individual resource to keep track of. A map of these are in the ResourceTracker. |
| */ |
| class Resource |
| { |
| public: |
| Resource() { _name[0] = '\0'; } |
| void increment(const int64_t size); |
| int64_t |
| getValue() const |
| { |
| return _value; |
| } |
| int64_t |
| getIncrement() const |
| { |
| return _incrementCount; |
| } |
| int64_t |
| getDecrement() const |
| { |
| return _decrementCount; |
| } |
| void |
| setSymbol(const void *symbol) |
| { |
| _symbol = symbol; |
| } |
| void |
| setName(const char *name) |
| { |
| strncpy(_name, name, sizeof(_name)); |
| _name[sizeof(_name) - 1] = '\0'; |
| } |
| void |
| setName(const void *symbol, const char *name) |
| { |
| Dl_info info; |
| dladdr(const_cast<void *>(symbol), &info); |
| snprintf(_name, sizeof(_name), "%s/%s", name, info.dli_sname); |
| } |
| const char * |
| getName() const |
| { |
| return _name; |
| } |
| const void * |
| getSymbol() const |
| { |
| return _symbol; |
| } |
| |
| private: |
| int64_t _incrementCount = 0; |
| int64_t _decrementCount = 0; |
| int64_t _value = 0; |
| const void *_symbol = nullptr; |
| char _name[128]; |
| }; |
| |
| void |
| Resource::increment(const int64_t size) |
| { |
| ink_atomic_increment(&_value, size); |
| if (size >= 0) { |
| ink_atomic_increment(&_incrementCount, 1); |
| } else { |
| ink_atomic_increment(&_decrementCount, 1); |
| } |
| } |
| |
| void |
| ResourceTracker::increment(const char *name, const int64_t size) |
| { |
| Resource &resource = lookup(name); |
| const char *lookup_name = resource.getName(); |
| if (lookup_name[0] == '\0') { |
| resource.setName(name); |
| } |
| resource.increment(size); |
| } |
| |
| void |
| ResourceTracker::increment(const void *symbol, const int64_t size, const char *name) |
| { |
| Resource &resource = lookup(static_cast<const char *>(symbol)); |
| if (resource.getSymbol() == nullptr && name != nullptr) { |
| resource.setName(symbol, name); |
| resource.setSymbol(symbol); |
| } |
| resource.increment(size); |
| } |
| |
| Resource & |
| ResourceTracker::lookup(const char *name) |
| { |
| Resource *resource = nullptr; |
| ink_mutex_acquire(&resourceLock); |
| std::map<const char *, Resource *>::iterator it = _resourceMap.find(name); |
| if (it != _resourceMap.end()) { |
| resource = it->second; |
| } else { |
| // create a new entry |
| resource = new Resource; |
| _resourceMap[name] = resource; |
| } |
| ink_mutex_release(&resourceLock); |
| ink_release_assert(resource != nullptr); |
| return *resource; |
| } |
| |
| void |
| ResourceTracker::dump(FILE *fd) |
| { |
| if (!res_track_memory) { |
| return; |
| } |
| int64_t total = 0; |
| |
| ink_mutex_acquire(&resourceLock); |
| if (!_resourceMap.empty()) { |
| fprintf(fd, "\n%-10s | %-10s | %-20s | %-10s | %-50s\n", "Allocs", "Frees", "Size In-use", "Avg Size", "Location"); |
| fprintf(fd, "-----------|------------|----------------------|------------|" |
| "--------------------------------------------------------------------\n"); |
| for (std::map<const char *, Resource *>::const_iterator it = _resourceMap.begin(); it != _resourceMap.end(); ++it) { |
| const Resource &resource = *it->second; |
| int64_t average_size = 0; |
| if (resource.getIncrement() - resource.getDecrement() > 0) { |
| average_size = resource.getValue() / (resource.getIncrement() - resource.getDecrement()); |
| } |
| fprintf(fd, "%10" PRId64 " | %10" PRId64 " | %20" PRId64 " | %10" PRId64 " | %-50s\n", resource.getIncrement(), |
| resource.getDecrement(), resource.getValue(), average_size, resource.getName()); |
| total += resource.getValue(); |
| } |
| fprintf(fd, " %20" PRId64 " | | %-50s\n", total, "TOTAL"); |
| fprintf(fd, "--------------------------------------------------------------" |
| "--------------------------------------------------------------------\n"); |
| } |
| |
| ink_mutex_release(&resourceLock); |
| |
| if (res_track_memory >= 2) { |
| fprintf(fd, "\n%-20s | %-20s | %-20s | %-20s\n", "Total Allocated", "Total Freed", "Currently Allocated", "Type"); |
| fprintf(fd, "---------------------|----------------------|----------------------|----------------------\n"); |
| fprintf(fd, "%20" PRId64 " | %20" PRId64 " | %20" PRId64 " | %-50s\n", ssl_memory_allocated, ssl_memory_freed, |
| ssl_memory_allocated - ssl_memory_freed, "SSL Allocated Memory"); |
| fprintf(fd, "---------------------|----------------------|----------------------|----------------------\n"); |
| } |
| } |