// -----------------------------------------------------------------------------
size_t MemoryCap::thread_cap = 0;
+size_t MemoryCap::preemptive_threshold = 0;
// -----------------------------------------------------------------------------
// public interface
mp_active_context.update_deallocs(n);
}
+bool MemoryCap::over_threshold()
+{
+ if ( !preemptive_threshold )
+ return false;
+
+ return s_tracker.used() >= preemptive_threshold;
+}
+
void MemoryCap::calculate(unsigned num_threads)
{
const MemoryConfig& config = *snort_conf->memory;
FatalError("per-thread memory cap is 0");
DebugFormat(DEBUG_MEMORY, "per-thread memory cap set to %zu", thread_cap);
+
+ if ( config.threshold )
+ {
+ preemptive_threshold = memory::calculate_threshold(thread_cap, config.threshold);
+ DebugFormat(DEBUG_MEMORY,
+ "per-thread pre-emptive action threshold set to %zu", preemptive_threshold);
+ }
}
} // namespace memory
static void update_allocations(size_t);
static void update_deallocations(size_t);
+ bool over_threshold();
+
// call from main thread before thread spawn
static void calculate(unsigned num_threads);
private:
static size_t thread_cap;
+ static size_t preemptive_threshold;
};
} // namespace memory
{
size_t cap = 0;
bool soft = false;
+ size_t threshold = 0;
constexpr MemoryConfig() = default;
};
{ "soft", Parameter::PT_BOOL, nullptr, "false",
"always succeed in allocating memory, even if above the cap" },
+ { "threshold", Parameter::PT_INT, "0:", "0",
+ "set the per-packet-thread threshold for preemptive cleanup actions "
+ "(percent, 0 to disable)" },
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
else if ( v.is("soft") )
sc->memory->soft = v.get_bool();
+ else if ( v.is("threshold") )
+ sc->memory->threshold = v.get_long();
+
else
return false;