diff options
Diffstat (limited to 'src/oom/oomd-util.h')
-rw-r--r-- | src/oom/oomd-util.h | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/oom/oomd-util.h b/src/oom/oomd-util.h new file mode 100644 index 0000000..87ecda8 --- /dev/null +++ b/src/oom/oomd-util.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include <stdbool.h> + +#include "hashmap.h" +#include "psi-util.h" + +#define GROWING_SIZE_PERCENTILE 80 + +extern const struct hash_ops oomd_cgroup_ctx_hash_ops; + +typedef struct OomdCGroupContext OomdCGroupContext; +typedef struct OomdSystemContext OomdSystemContext; + +typedef int (oomd_compare_t)(OomdCGroupContext * const *, OomdCGroupContext * const *); + +struct OomdCGroupContext { + char *path; + + ResourcePressure memory_pressure; + + uint64_t current_memory_usage; + + uint64_t memory_min; + uint64_t memory_low; + uint64_t swap_usage; + + uint64_t last_pgscan; + uint64_t pgscan; + + /* These are only used by oomd_pressure_above for acting on high memory pressure. */ + loadavg_t mem_pressure_limit; + usec_t last_hit_mem_pressure_limit; +}; + +struct OomdSystemContext { + uint64_t swap_total; + uint64_t swap_used; +}; + +OomdCGroupContext *oomd_cgroup_context_free(OomdCGroupContext *ctx); +DEFINE_TRIVIAL_CLEANUP_FUNC(OomdCGroupContext*, oomd_cgroup_context_free); + +/* All hashmaps used with these functions are expected to be of the form + * key: cgroup paths -> value: OomdCGroupContext. */ + +/* Scans all the OomdCGroupContexts in `h` and returns 1 and a set of pointers to those OomdCGroupContexts in `ret` + * if any of them have exceeded their supplied memory pressure limits for the `duration` length of time. + * `last_hit_mem_pressure_limit` is updated accordingly for each entry when the limit is exceeded, and when it returns + * below the limit. + * Returns 0 and sets `ret` to an empty set if no entries exceeded limits for `duration`. + * Returns -ENOMEM for allocation errors. */ +int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret); + +/* Sum up current OomdCGroupContexts' pgscan values and last interval's pgscan values in `h`. Returns true if the + * current sum is higher than the last interval's sum (there was some reclaim activity). */ +bool oomd_memory_reclaim(Hashmap *h); + +/* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */ +bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent); + +static inline int compare_pgscan(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) { + assert(c1); + assert(c2); + + if ((*c1)->pgscan > (*c2)->pgscan) + return -1; + else if ((*c1)->pgscan < (*c2)->pgscan) + return 1; + else + return 0; +} + +static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) { + assert(c1); + assert(c2); + + if ((*c1)->swap_usage > (*c2)->swap_usage) + return -1; + else if ((*c1)->swap_usage < (*c2)->swap_usage) + return 1; + else + return 0; +} + +/* Get an array of OomdCGroupContexts from `h`, qsorted from largest to smallest values according to `compare_func`. + * If `prefix` is not NULL, only include OomdCGroupContexts whose paths start with prefix. Otherwise all paths are sorted. + * Returns the number of sorted items; negative on error. */ +int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const char *prefix, OomdCGroupContext ***ret); + +/* Returns a negative value on error, 0 if no processes were killed, or 1 if processes were killed. */ +int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run); + +/* The following oomd_kill_by_* functions return 1 if processes were killed, or negative otherwise. */ +/* If `prefix` is supplied, only cgroups whose paths start with `prefix` are eligible candidates. Otherwise, + * everything in `h` is a candidate. */ +int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run); +int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run); + +int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret); +int oomd_system_context_acquire(const char *proc_swaps_path, OomdSystemContext *ret); + +/* Get the OomdCGroupContext of `path` and insert it into `new_h`. The key for the inserted context will be `path`. + * + * `old_h` is used to get data used to calculate prior interval information. `old_h` can be NULL in which case there + * was no prior data to reference. */ +int oomd_insert_cgroup_context(Hashmap *old_h, Hashmap *new_h, const char *path); + +void oomd_dump_swap_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix); +void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix); +void oomd_dump_system_context(const OomdSystemContext *ctx, FILE *f, const char *prefix); |