]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
61ff7397 AZ |
2 | #pragma once |
3 | ||
4 | #include <stdbool.h> | |
5 | ||
6 | #include "hashmap.h" | |
7 | #include "psi-util.h" | |
8 | ||
9 | #define GROWING_SIZE_PERCENTILE 80 | |
10 | ||
11 | extern const struct hash_ops oomd_cgroup_ctx_hash_ops; | |
12 | ||
13 | typedef struct OomdCGroupContext OomdCGroupContext; | |
14 | typedef struct OomdSystemContext OomdSystemContext; | |
15 | ||
16 | typedef int (oomd_compare_t)(OomdCGroupContext * const *, OomdCGroupContext * const *); | |
17 | ||
18 | struct OomdCGroupContext { | |
19 | char *path; | |
20 | ||
21 | ResourcePressure memory_pressure; | |
22 | ||
23 | uint64_t current_memory_usage; | |
24 | ||
25 | uint64_t memory_min; | |
26 | uint64_t memory_low; | |
27 | uint64_t swap_usage; | |
28 | ||
29 | uint64_t last_pgscan; | |
30 | uint64_t pgscan; | |
31 | ||
32 | /* These are only used by oomd_pressure_above for acting on high memory pressure. */ | |
33 | loadavg_t mem_pressure_limit; | |
34 | usec_t last_hit_mem_pressure_limit; | |
35 | }; | |
36 | ||
37 | struct OomdSystemContext { | |
38 | uint64_t swap_total; | |
39 | uint64_t swap_used; | |
40 | }; | |
41 | ||
42 | OomdCGroupContext *oomd_cgroup_context_free(OomdCGroupContext *ctx); | |
43 | DEFINE_TRIVIAL_CLEANUP_FUNC(OomdCGroupContext*, oomd_cgroup_context_free); | |
44 | ||
45 | /* All hashmaps used with these functions are expected to be of the form | |
46 | * key: cgroup paths -> value: OomdCGroupContext. */ | |
47 | ||
48 | /* Scans all the OomdCGroupContexts in `h` and returns 1 and a set of pointers to those OomdCGroupContexts in `ret` | |
49 | * if any of them have exceeded their supplied memory pressure limits for the `duration` length of time. | |
50 | * `last_hit_mem_pressure_limit` is updated accordingly for each entry when the limit is exceeded, and when it returns | |
51 | * below the limit. | |
52 | * Returns 0 and sets `ret` to an empty set if no entries exceeded limits for `duration`. | |
53 | * Returns -ENOMEM for allocation errors. */ | |
54 | int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret); | |
55 | ||
56 | /* Sum up current OomdCGroupContexts' pgscan values and last interval's pgscan values in `h`. Returns true if the | |
57 | * current sum is higher than the last interval's sum (there was some reclaim activity). */ | |
58 | bool oomd_memory_reclaim(Hashmap *h); | |
59 | ||
60 | /* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */ | |
61 | bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent); | |
62 | ||
63 | static inline int compare_pgscan(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) { | |
64 | assert(c1); | |
65 | assert(c2); | |
66 | ||
67 | if ((*c1)->pgscan > (*c2)->pgscan) | |
68 | return -1; | |
69 | else if ((*c1)->pgscan < (*c2)->pgscan) | |
70 | return 1; | |
71 | else | |
72 | return 0; | |
73 | } | |
74 | ||
75 | static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) { | |
76 | assert(c1); | |
77 | assert(c2); | |
78 | ||
79 | if ((*c1)->swap_usage > (*c2)->swap_usage) | |
80 | return -1; | |
81 | else if ((*c1)->swap_usage < (*c2)->swap_usage) | |
82 | return 1; | |
83 | else | |
84 | return 0; | |
85 | } | |
86 | ||
87 | /* Get an array of OomdCGroupContexts from `h`, qsorted from largest to smallest values according to `compare_func`. | |
88 | * If `prefix` is not NULL, only include OomdCGroupContexts whose paths start with prefix. Otherwise all paths are sorted. | |
89 | * Returns the number of sorted items; negative on error. */ | |
90 | int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const char *prefix, OomdCGroupContext ***ret); | |
91 | ||
92 | /* Returns a negative value on error, 0 if no processes were killed, or 1 if processes were killed. */ | |
93 | int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run); | |
94 | ||
95 | /* The following oomd_kill_by_* functions return 1 if processes were killed, or negative otherwise. */ | |
96 | /* If `prefix` is supplied, only cgroups whose paths start with `prefix` are eligible candidates. Otherwise, | |
97 | * everything in `h` is a candidate. */ | |
98 | int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run); | |
99 | int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run); | |
100 | ||
101 | int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret); | |
102 | int oomd_system_context_acquire(const char *proc_swaps_path, OomdSystemContext *ret); | |
103 | ||
104 | /* Get the OomdCGroupContext of `path` and insert it into `new_h`. The key for the inserted context will be `path`. | |
105 | * | |
106 | * `old_h` is used to get data used to calculate prior interval information. `old_h` can be NULL in which case there | |
107 | * was no prior data to reference. */ | |
108 | int oomd_insert_cgroup_context(Hashmap *old_h, Hashmap *new_h, const char *path); | |
5c616ecf AZ |
109 | |
110 | void oomd_dump_swap_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix); | |
111 | void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix); | |
112 | void oomd_dump_system_context(const OomdSystemContext *ctx, FILE *f, const char *prefix); |