Coverage Report

Created: 2026-05-16 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib/cpu-limit.h
Line
Count
Source
1
#ifndef CPU_LIMIT
2
#define CPU_LIMIT
3
4
struct cpu_limit;
5
6
enum cpu_limit_type {
7
  CPU_LIMIT_TYPE_USER = BIT(0),
8
  CPU_LIMIT_TYPE_SYSTEM = BIT(1),
9
};
10
#define CPU_LIMIT_TYPE_ALL (CPU_LIMIT_TYPE_USER | CPU_LIMIT_TYPE_SYSTEM)
11
12
/* Start tracking CPU usage. This internally uses setrlimit(RLIMIT_CPU) to
13
   trigger SIGXCPU to avoid constantly calling getrlimit() to check if the CPU
14
   usage has reached a limit. Once all limits created by this API are released,
15
   the original CPU resource limits are restored (if any).
16
17
   CPU time limits can be nested, i.e. they are never independent. The outer
18
   limits contain the bounded maximum limit for the inner limits. For example
19
   the code execution flow might be:
20
    - Set 30s CPU limit (outer limit)
21
    - Use up 5s of CPU
22
    - Set 40s CPU limit (inner limit)
23
    - Infinite loop
24
   The inner loop's limit won't even be reached here. After the inner loops
25
   runs for 25 seconds, the outer loop's 30s limit is reached. This causes
26
   both the inner and the other limit's cpu_limit_exceeded() to return TRUE.
27
   It's expected that the inner execution stops and returns back to the outer
28
   execution, which notices that the outer execution has also reached the limit.
29
30
   Another example where the inner limit is reached:
31
    - Set 30s CPU limit (outer limit)
32
    - Use up 5s of CPU
33
    - Set 10s CPU limit (inner limit)
34
    - Infinite loop
35
   Here the inner 10s limit is reached, and the inner execution stops. The
36
   outer execution could still run for another 15 seconds.
37
38
   Example usage:
39
40
   bool limit_reached = FALSE;
41
   limit = cpu_limit_init(5, CPU_LIMIT_TYPE_ALL);
42
   while (long_operation_iterate_once()) {
43
     if (cpu_limit_exceeded(limit)) {
44
       limit_reached = TRUE; // operation took >=5 secs
45
       break;
46
     }
47
   }
48
   cpu_limit_deinit(&limit);
49
*/
50
struct cpu_limit *
51
cpu_limit_init(unsigned int cpu_limit_secs, enum cpu_limit_type type);
52
void cpu_limit_deinit(struct cpu_limit **_climit);
53
54
/* Returns TRUE if the CPU limit has been exceeded for this limit or any of its
55
   parents. */
56
bool cpu_limit_exceeded(struct cpu_limit *climit);
57
58
unsigned int cpu_limit_get_usage_msecs(struct cpu_limit *climit,
59
               enum cpu_limit_type type);
60
61
static inline unsigned int
62
cpu_limit_get_usage_secs(struct cpu_limit *climit, enum cpu_limit_type type)
63
0
{
64
0
  return cpu_limit_get_usage_msecs(climit, type) / 1000;
65
0
}
Unexecuted instantiation: sieve-interpreter.c:cpu_limit_get_usage_secs
Unexecuted instantiation: cpu-limit.c:cpu_limit_get_usage_secs
66
67
#endif