Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2015 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <stdlib.h>
7 : : #include <errno.h>
8 : :
9 : : #include <eal_export.h>
10 : : #include <rte_string_fns.h>
11 : : #include <rte_common.h>
12 : : #include <rte_cycles.h>
13 : : #include <rte_branch_prediction.h>
14 : :
15 : : #include "rte_jobstats.h"
16 : :
17 : : #define ADD_TIME_MIN_MAX(obj, type, value) do { \
18 : : typeof(value) tmp = (value); \
19 : : (obj)->type ## _time += tmp; \
20 : : if (tmp < (obj)->min_ ## type ## _time) \
21 : : (obj)->min_ ## type ## _time = tmp; \
22 : : if (tmp > (obj)->max_ ## type ## _time) \
23 : : (obj)->max_ ## type ## _time = tmp; \
24 : : } while (0)
25 : :
26 : : #define RESET_TIME_MIN_MAX(obj, type) do { \
27 : : (obj)->type ## _time = 0; \
28 : : (obj)->min_ ## type ## _time = UINT64_MAX; \
29 : : (obj)->max_ ## type ## _time = 0; \
30 : : } while (0)
31 : :
32 : : static inline uint64_t
33 : : get_time(void)
34 : : {
35 : : rte_rmb();
36 : : return rte_get_timer_cycles();
37 : : }
38 : :
39 : : /* Those are steps used to adjust job period.
40 : : * Experiments show that for forwarding apps the up step must be less than down
41 : : * step to achieve optimal performance.
42 : : */
43 : : #define JOB_UPDATE_STEP_UP 1
44 : : #define JOB_UPDATE_STEP_DOWN 4
45 : :
46 : : /*
47 : : * Default update function that implements simple period adjustment.
48 : : */
49 : : static void
50 : 0 : default_update_function(struct rte_jobstats *job, int64_t result)
51 : : {
52 : 0 : int64_t err = job->target - result;
53 : :
54 : : /* Job is happy. Nothing to do */
55 [ # # ]: 0 : if (err == 0)
56 : : return;
57 : :
58 [ # # ]: 0 : if (err > 0) {
59 [ # # ]: 0 : if (job->period + JOB_UPDATE_STEP_UP < job->max_period)
60 : 0 : job->period += JOB_UPDATE_STEP_UP;
61 : : } else {
62 [ # # ]: 0 : if (job->min_period + JOB_UPDATE_STEP_DOWN < job->period)
63 : 0 : job->period -= JOB_UPDATE_STEP_DOWN;
64 : : }
65 : : }
66 : :
67 : : RTE_EXPORT_SYMBOL(rte_jobstats_context_init)
68 : : int
69 : 0 : rte_jobstats_context_init(struct rte_jobstats_context *ctx)
70 : : {
71 [ # # ]: 0 : if (ctx == NULL)
72 : : return -EINVAL;
73 : :
74 : : /* Init only needed parameters. Zero out everything else. */
75 : : memset(ctx, 0, sizeof(struct rte_jobstats_context));
76 : :
77 : 0 : rte_jobstats_context_reset(ctx);
78 : :
79 : 0 : return 0;
80 : : }
81 : :
82 : : RTE_EXPORT_SYMBOL(rte_jobstats_context_start)
83 : : void
84 : 0 : rte_jobstats_context_start(struct rte_jobstats_context *ctx)
85 : : {
86 : : uint64_t now;
87 : :
88 : 0 : ctx->loop_executed_jobs = 0;
89 : :
90 : : now = get_time();
91 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time);
92 : 0 : ctx->state_time = now;
93 : 0 : }
94 : :
95 : : RTE_EXPORT_SYMBOL(rte_jobstats_context_finish)
96 : : void
97 : 0 : rte_jobstats_context_finish(struct rte_jobstats_context *ctx)
98 : : {
99 : : uint64_t now;
100 : :
101 [ # # ]: 0 : if (likely(ctx->loop_executed_jobs))
102 : 0 : ctx->loop_cnt++;
103 : :
104 : : now = get_time();
105 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time);
106 : 0 : ctx->state_time = now;
107 : 0 : }
108 : :
109 : : RTE_EXPORT_SYMBOL(rte_jobstats_context_reset)
110 : : void
111 : 0 : rte_jobstats_context_reset(struct rte_jobstats_context *ctx)
112 : : {
113 : 0 : RESET_TIME_MIN_MAX(ctx, exec);
114 : 0 : RESET_TIME_MIN_MAX(ctx, management);
115 : 0 : ctx->start_time = get_time();
116 : 0 : ctx->state_time = ctx->start_time;
117 : 0 : ctx->job_exec_cnt = 0;
118 : 0 : ctx->loop_cnt = 0;
119 : 0 : }
120 : :
121 : : RTE_EXPORT_SYMBOL(rte_jobstats_set_target)
122 : : void
123 : 0 : rte_jobstats_set_target(struct rte_jobstats *job, int64_t target)
124 : : {
125 : 0 : job->target = target;
126 : 0 : }
127 : :
128 : : RTE_EXPORT_SYMBOL(rte_jobstats_start)
129 : : int
130 : 0 : rte_jobstats_start(struct rte_jobstats_context *ctx, struct rte_jobstats *job)
131 : : {
132 : : uint64_t now;
133 : :
134 : : /* Some sanity check. */
135 [ # # # # ]: 0 : if (unlikely(ctx == NULL || job == NULL || job->context != NULL))
136 : : return -EINVAL;
137 : :
138 : : /* Link job with context object. */
139 : 0 : job->context = ctx;
140 : :
141 : : now = get_time();
142 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time);
143 : 0 : ctx->state_time = now;
144 : :
145 : 0 : return 0;
146 : : }
147 : :
148 : : RTE_EXPORT_SYMBOL(rte_jobstats_abort)
149 : : int
150 : 0 : rte_jobstats_abort(struct rte_jobstats *job)
151 : : {
152 : : struct rte_jobstats_context *ctx;
153 : : uint64_t now, exec_time;
154 : :
155 : : /* Some sanity check. */
156 [ # # # # ]: 0 : if (unlikely(job == NULL || job->context == NULL))
157 : : return -EINVAL;
158 : :
159 : : ctx = job->context;
160 : : now = get_time();
161 : 0 : exec_time = now - ctx->state_time;
162 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(ctx, management, exec_time);
163 : 0 : ctx->state_time = now;
164 : 0 : job->context = NULL;
165 : :
166 : 0 : return 0;
167 : : }
168 : :
169 : : RTE_EXPORT_SYMBOL(rte_jobstats_finish)
170 : : int
171 : 0 : rte_jobstats_finish(struct rte_jobstats *job, int64_t job_value)
172 : : {
173 : : struct rte_jobstats_context *ctx;
174 : : uint64_t now, exec_time;
175 : : int need_update;
176 : :
177 : : /* Some sanity check. */
178 [ # # # # ]: 0 : if (unlikely(job == NULL || job->context == NULL))
179 : : return -EINVAL;
180 : :
181 : 0 : need_update = job->target != job_value;
182 : : /* Adjust period only if job is unhappy of its current period. */
183 [ # # ]: 0 : if (need_update)
184 : 0 : (*job->update_period_cb)(job, job_value);
185 : :
186 : 0 : ctx = job->context;
187 : :
188 : : /* Update execution time is considered as runtime so get time after it is
189 : : * executed. */
190 : : now = get_time();
191 : 0 : exec_time = now - ctx->state_time;
192 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(job, exec, exec_time);
193 [ # # # # ]: 0 : ADD_TIME_MIN_MAX(ctx, exec, exec_time);
194 : :
195 : 0 : ctx->state_time = now;
196 : :
197 : 0 : ctx->loop_executed_jobs++;
198 : 0 : ctx->job_exec_cnt++;
199 : :
200 : 0 : job->exec_cnt++;
201 : 0 : job->context = NULL;
202 : :
203 : 0 : return need_update;
204 : : }
205 : :
206 : : RTE_EXPORT_SYMBOL(rte_jobstats_set_period)
207 : : void
208 : 0 : rte_jobstats_set_period(struct rte_jobstats *job, uint64_t period,
209 : : uint8_t saturate)
210 : : {
211 [ # # ]: 0 : if (saturate != 0) {
212 [ # # ]: 0 : if (period < job->min_period)
213 : : period = job->min_period;
214 : 0 : else if (period > job->max_period)
215 : : period = job->max_period;
216 : : }
217 : :
218 : 0 : job->period = period;
219 : 0 : }
220 : :
221 : : RTE_EXPORT_SYMBOL(rte_jobstats_set_min)
222 : : void
223 : 0 : rte_jobstats_set_min(struct rte_jobstats *job, uint64_t period)
224 : : {
225 : 0 : job->min_period = period;
226 [ # # ]: 0 : if (job->period < period)
227 : 0 : job->period = period;
228 : 0 : }
229 : :
230 : : RTE_EXPORT_SYMBOL(rte_jobstats_set_max)
231 : : void
232 : 0 : rte_jobstats_set_max(struct rte_jobstats *job, uint64_t period)
233 : : {
234 : 0 : job->max_period = period;
235 [ # # ]: 0 : if (job->period > period)
236 : 0 : job->period = period;
237 : 0 : }
238 : :
239 : : RTE_EXPORT_SYMBOL(rte_jobstats_init)
240 : : int
241 : 0 : rte_jobstats_init(struct rte_jobstats *job, const char *name,
242 : : uint64_t min_period, uint64_t max_period, uint64_t initial_period,
243 : : int64_t target)
244 : : {
245 [ # # ]: 0 : if (job == NULL)
246 : : return -EINVAL;
247 : :
248 : 0 : job->period = initial_period;
249 : 0 : job->min_period = min_period;
250 : 0 : job->max_period = max_period;
251 : 0 : job->target = target;
252 : 0 : job->update_period_cb = &default_update_function;
253 : 0 : rte_jobstats_reset(job);
254 [ # # ]: 0 : strlcpy(job->name, name == NULL ? "" : name, RTE_DIM(job->name));
255 : 0 : job->context = NULL;
256 : :
257 : 0 : return 0;
258 : : }
259 : :
260 : : RTE_EXPORT_SYMBOL(rte_jobstats_set_update_period_function)
261 : : void
262 : 0 : rte_jobstats_set_update_period_function(struct rte_jobstats *job,
263 : : rte_job_update_period_cb_t update_period_cb)
264 : : {
265 [ # # ]: 0 : if (update_period_cb == NULL)
266 : : update_period_cb = default_update_function;
267 : :
268 : 0 : job->update_period_cb = update_period_cb;
269 : 0 : }
270 : :
271 : : RTE_EXPORT_SYMBOL(rte_jobstats_reset)
272 : : void
273 : 0 : rte_jobstats_reset(struct rte_jobstats *job)
274 : : {
275 : 0 : RESET_TIME_MIN_MAX(job, exec);
276 : 0 : job->exec_cnt = 0;
277 : 0 : }
|