#include "main/snort_config.h"
#include "main/snort_types.h"
#include "main/thread.h"
-#include "managers/module_manager.h"
#include "time/periodic.h"
#include "trace/trace_api.h"
#include "utils/stats.h"
static bool over_limit = false;
static std::atomic<uint64_t> current_epoch { 0 };
+static std::atomic<uint64_t> start_up_use { 0 };
+static std::atomic<uint64_t> max_in_use { 0 };
+
+// The most recent epoch reported by jemalloc
+static std::atomic<uint64_t> latest_epoch { 0 };
static THREAD_LOCAL uint64_t start_dealloc = 0;
static THREAD_LOCAL uint64_t start_alloc = 0;
static void epoch_check(void*)
{
uint64_t epoch, total;
- heap->get_process_total(epoch, total);
+ heap->get_process_total(epoch, total, true);
bool prior = over_limit;
over_limit = limit and total > limit;
else
current_epoch = 0;
-#ifndef REG_TEST
- MemoryCounts& mc = MemoryCap::get_mem_stats();
-#else
- auto orig_type = get_thread_type();
-
- // Due to call of epoch_check in first pthread
- // for build with REG_TEST, we need make that
- // pthread think that we're main thread
- set_thread_type(STHREAD_TYPE_MAIN);
- MemoryCounts& mc = MemoryCap::get_mem_stats();
- set_thread_type(orig_type);
-#endif
-
- if ( total > mc.max_in_use )
- mc.max_in_use = total;
+ if ( !start_up_use )
+ start_up_use = total;
- mc.cur_in_use = total;
- mc.epochs++;
+ if ( total > max_in_use )
+ max_in_use = total;
- // for reporting / tracking only
- uint64_t all, act, res, ret;
- heap->get_aux_counts(all, act, res, ret);
-
- mc.app_all = all;
- mc.active = act;
- mc.resident = res;
- mc.retained = ret;
+ latest_epoch = epoch;
}
// -----------------------------------------------------------------------------
void MemoryCap::init(unsigned n)
{
assert(in_main_thread());
- pkt_mem_stats.resize(n + 1);
+ pkt_mem_stats.resize(n);
#ifdef UNIT_TEST
pkt_mem_stats[0] = { };
#endif
epoch_check(nullptr);
-
- MemoryCounts& mc = get_mem_stats();
- mc.start_up_use = mc.cur_in_use;
}
void MemoryCap::stop()
-{ epoch_check(nullptr); }
+{
+ epoch_check(nullptr);
+ update_global_stats();
+}
void MemoryCap::thread_init()
{
MemoryCounts& MemoryCap::get_mem_stats()
{
- // main thread stats do not overlap with packet threads
+ // main thread stats overlap with packet thread 1
if ( in_main_thread() )
return pkt_mem_stats[0];
- auto id = get_instance_id() + 1;
+ auto id = get_instance_id();
return pkt_mem_stats[id];
}
// required to capture any update in final epoch
// which happens after packet threads have stopped
-void MemoryCap::update_pegs()
+void MemoryCap::update_pegs(PegCount* pc)
{
+ MemoryCounts* mp = (MemoryCounts*)pc;
+ const MemoryCounts& mc = get_mem_stats();
+
if ( config.enabled )
- ModuleManager::accumulate_module("memory");
+ {
+ mp->epochs = mc.epochs;
+ mp->cur_in_use = mc.cur_in_use;
+ }
+ else
+ {
+ mp->allocated = 0;
+ mp->deallocated = 0;
+ }
+}
+
+void MemoryCap::update_global_stats()
+{
+ if ( !pkt_mem_stats.size() )
+ return;
+
+ MemoryCounts& mc = pkt_mem_stats[0];
+
+ uint64_t epoch, total;
+ heap->get_process_total(epoch, total, false);
+
+ mc.max_in_use = max_in_use;
+
+ mc.cur_in_use = total;
+
+ if ( epoch > latest_epoch )
+ latest_epoch = epoch;
+
+ mc.epochs = latest_epoch;
+ mc.start_up_use = start_up_use;
+
+ // for reporting / tracking only
+ uint64_t all, act, res, ret;
+ heap->get_aux_counts(all, act, res, ret);
+
+ mc.app_all = all;
+ mc.active = act;
+ mc.resident = res;
+ mc.retained = ret;
}
// called at startup and shutdown
#include "memory/memory_cap.h"
+#include <vector>
+
#include "log/messages.h"
#include "main/thread.h"
-#include "managers/module_manager.h"
+#include "main/thread_config.h"
#include "profiler/profiler.h"
#include "time/periodic.h"
#include "trace/trace_api.h"
#include <CppUTestExt/MockSupport.h>
using namespace memory;
+using IndexVec = std::vector<unsigned>;
//--------------------------------------------------------------------------
// stubs
unsigned get_instance_id()
{ return 0; }
+
+unsigned ThreadConfig::get_instance_max()
+{ return 0; }
+
}
+void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
+void show_stats(PegCount*, const PegInfo*, const IndexVec&, const char*, FILE*) { }
+
THREAD_LOCAL const Trace* memory_trace = nullptr;
#ifndef REG_TEST
void Periodic::register_handler(PeriodicHook, void*, uint16_t, uint32_t) { }
#endif
-void ModuleManager::accumulate_module(const char*) { }
-
//--------------------------------------------------------------------------
// mocks
//--------------------------------------------------------------------------
void thread_init() override
{ thread_init_calls++; }
- void get_process_total(uint64_t& e, uint64_t& t) override
- { e = ++epoch; t = total; }
+ void get_process_total(uint64_t& e, uint64_t& t, bool bump_epoch) override
+ {
+ t = total;
+ if ( bump_epoch )
+ e = ++epoch;
+ else
+ e = epoch;
+ }
void get_thread_allocs(uint64_t& a, uint64_t& d) override
{ a = alloc; d = dealloc; }
}
-void set_thread_type(SThreadType)
-{ pkt_thread = false; }
-
static void free_space()
{
pkt_thread = true;
pkt_thread = false;
}
-static MemoryCounts& get_main_stats()
-{
- return MemoryCap::get_mem_stats();
-}
-
-static MemoryCounts& get_pkt_stats()
-{
- pkt_thread = true;
- MemoryCounts& res = MemoryCap::get_mem_stats();
- pkt_thread = false;
- return res;
-}
-
//--------------------------------------------------------------------------
// tests
//--------------------------------------------------------------------------
MemoryCap::start(config, pruner);
MemoryCap::thread_init();
- const MemoryCounts& mc = get_main_stats();
- const MemoryCounts& pc = get_pkt_stats();
+ const MemoryCounts& mc = MemoryCap::get_mem_stats();
+ MemoryCap::update_global_stats();
CHECK(mc.start_up_use == start);
fd.flows = 3;
free_space(); // finish pruning
UNSIGNED_LONGS_EQUAL(1, fd.flows);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_decrease);
free_space();
UNSIGNED_LONGS_EQUAL(1, fd.flows);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_decrease);
periodic_check(); // still over the limit
CHECK(heap->epoch == 3);
free_space(); // abort
UNSIGNED_LONGS_EQUAL(0, fd.flows);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_decrease);
heap->total = cap + 1; // over the limit
periodic_check();
free_space(); // abort, reap_increase update
UNSIGNED_LONGS_EQUAL(0, fd.flows);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(4, pc.reap_increase);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(4, mc.reap_increase);
heap->total = cap + 1; // over the limit
periodic_check();
heap->alloc += 3;
free_space(); // abort, reap_increase update
+ memory::MemoryCap::update_global_stats();
UNSIGNED_LONGS_EQUAL(0, fd.flows);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(6, pc.reap_increase);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(6, mc.reap_increase);
UNSIGNED_LONGS_EQUAL(start, mc.start_up_use);
UNSIGNED_LONGS_EQUAL(cap + 1, mc.max_in_use);
UNSIGNED_LONGS_EQUAL(cap, mc.cur_in_use);
UNSIGNED_LONGS_EQUAL(heap->epoch, mc.epochs);
- UNSIGNED_LONGS_EQUAL(heap->alloc, pc.allocated);
- UNSIGNED_LONGS_EQUAL(heap->dealloc, pc.deallocated);
+ UNSIGNED_LONGS_EQUAL(heap->alloc, mc.allocated);
+ UNSIGNED_LONGS_EQUAL(heap->dealloc, mc.deallocated);
- UNSIGNED_LONGS_EQUAL(4, pc.reap_cycles);
- UNSIGNED_LONGS_EQUAL(5, pc.reap_attempts);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_failures);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_aborts);
+ UNSIGNED_LONGS_EQUAL(4, mc.reap_cycles);
+ UNSIGNED_LONGS_EQUAL(5, mc.reap_attempts);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_failures);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_aborts);
heap->total = start;
MemoryCap::stop();
+ memory::MemoryCap::update_global_stats();
CHECK(mc.epochs == heap->epoch);
CHECK(mc.cur_in_use == start);
}
free_space();
CHECK(fd.flows == 0);
- const MemoryCounts& pc = get_pkt_stats();
- UNSIGNED_LONGS_EQUAL(1, pc.reap_cycles);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_attempts);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_failures);
- UNSIGNED_LONGS_EQUAL(1, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_increase);
+ const MemoryCounts& mc = MemoryCap::get_mem_stats();
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_cycles);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_attempts);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_failures);
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_increase);
MemoryCap::stop();
}
free_space();
CHECK(fd.flows == 1);
- const MemoryCounts& pc = get_pkt_stats();
- UNSIGNED_LONGS_EQUAL(2, pc.reap_cycles);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_attempts);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_failures);
- UNSIGNED_LONGS_EQUAL(11, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_increase);
+ const MemoryCounts& mc = MemoryCap::get_mem_stats();
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_cycles);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_attempts);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_failures);
+ UNSIGNED_LONGS_EQUAL(11, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_increase);
MemoryCap::stop();
}
MemoryCap::start(config, pruner);
MemoryCap::thread_init();
- const MemoryCounts& pc = get_pkt_stats();
+ const MemoryCounts& mc = MemoryCap::get_mem_stats();
fd.flows = 1;
heap->total = cap + 1;
free_space(); // reap failure
CHECK(fd.flows == -1);
- UNSIGNED_LONGS_EQUAL(1, pc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_decrease);
fd.flows = 1;
heap->total = cap + 1;
free_space(); // reap failure, reap_increase update
CHECK(fd.flows == -1);
- UNSIGNED_LONGS_EQUAL(1, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_increase);
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_increase);
fd.flows = 1;
heap->total = cap + 1;
free_space(); // reap failure, reap_increase update
CHECK(fd.flows == -1);
- UNSIGNED_LONGS_EQUAL(1, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_increase);
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_increase);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_cycles);
- UNSIGNED_LONGS_EQUAL(6, pc.reap_attempts);
- UNSIGNED_LONGS_EQUAL(3, pc.reap_failures);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_cycles);
+ UNSIGNED_LONGS_EQUAL(6, mc.reap_attempts);
+ UNSIGNED_LONGS_EQUAL(3, mc.reap_failures);
MemoryCap::stop();
}
free_space();
UNSIGNED_LONGS_EQUAL(0, fd.flows);
- const MemoryCounts& pc = get_pkt_stats();
- UNSIGNED_LONGS_EQUAL(1, pc.reap_cycles);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_attempts);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_failures);
- UNSIGNED_LONGS_EQUAL(2, pc.reap_decrease);
- UNSIGNED_LONGS_EQUAL(0, pc.reap_increase);
+ const MemoryCounts& mc = MemoryCap::get_mem_stats();
+ UNSIGNED_LONGS_EQUAL(1, mc.reap_cycles);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_attempts);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_failures);
+ UNSIGNED_LONGS_EQUAL(2, mc.reap_decrease);
+ UNSIGNED_LONGS_EQUAL(0, mc.reap_increase);
MemoryCap::stop();
}