examples/ip_pipeline: remove config
[dpdk.git] / examples / ip_pipeline / thread.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2015 Intel Corporation
3  */
4
5 #include <rte_common.h>
6 #include <rte_cycles.h>
7 #include <rte_pipeline.h>
8
9 #include "app.h"
10 #include "thread.h"
11
12 static inline void *
13 thread_msg_recv(struct rte_ring *r)
14 {
15         void *msg;
16         int status = rte_ring_sc_dequeue(r, &msg);
17
18         if (status != 0)
19                 return NULL;
20
21         return msg;
22 }
23
24 static inline void
25 thread_msg_send(struct rte_ring *r,
26         void *msg)
27 {
28         int status;
29
30         do {
31                 status = rte_ring_sp_enqueue(r, msg);
32         } while (status == -ENOBUFS);
33 }
34
35 static int
36 thread_pipeline_enable(struct app_thread_data *t,
37                 struct thread_pipeline_enable_msg_req *req)
38 {
39         struct app_thread_pipeline_data *p;
40
41         if (req->f_run == NULL) {
42                 if (t->n_regular >= APP_MAX_THREAD_PIPELINES)
43                         return -1;
44         } else {
45                 if (t->n_custom >= APP_MAX_THREAD_PIPELINES)
46                         return -1;
47         }
48
49         p = (req->f_run == NULL) ?
50                 &t->regular[t->n_regular] :
51                 &t->custom[t->n_custom];
52
53         p->pipeline_id = req->pipeline_id;
54         p->be = req->be;
55         p->f_run = req->f_run;
56         p->f_timer = req->f_timer;
57         p->timer_period = req->timer_period;
58         p->deadline = 0;
59
60         if (req->f_run == NULL)
61                 t->n_regular++;
62         else
63                 t->n_custom++;
64
65         return 0;
66 }
67
68 static int
69 thread_pipeline_disable(struct app_thread_data *t,
70                 struct thread_pipeline_disable_msg_req *req)
71 {
72         uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular));
73         uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom));
74         uint32_t i;
75
76         /* search regular pipelines of current thread */
77         for (i = 0; i < n_regular; i++) {
78                 if (t->regular[i].pipeline_id != req->pipeline_id)
79                         continue;
80
81                 if (i < n_regular - 1)
82                         memcpy(&t->regular[i],
83                           &t->regular[i+1],
84                           (n_regular - 1 - i) * sizeof(struct app_thread_pipeline_data));
85
86                 n_regular--;
87                 t->n_regular = n_regular;
88
89                 return 0;
90         }
91
92         /* search custom pipelines of current thread */
93         for (i = 0; i < n_custom; i++) {
94                 if (t->custom[i].pipeline_id != req->pipeline_id)
95                         continue;
96
97                 if (i < n_custom - 1)
98                         memcpy(&t->custom[i],
99                           &t->custom[i+1],
100                           (n_custom - 1 - i) * sizeof(struct app_thread_pipeline_data));
101
102                 n_custom--;
103                 t->n_custom = n_custom;
104
105                 return 0;
106         }
107
108         /* return if pipeline not found */
109         return -1;
110 }
111
112 static int
113 thread_msg_req_handle(struct app_thread_data *t)
114 {
115         void *msg_ptr;
116         struct thread_msg_req *req;
117         struct thread_msg_rsp *rsp;
118
119         msg_ptr = thread_msg_recv(t->msgq_in);
120         req = msg_ptr;
121         rsp = msg_ptr;
122
123         if (req != NULL)
124                 switch (req->type) {
125                 case THREAD_MSG_REQ_PIPELINE_ENABLE: {
126                         rsp->status = thread_pipeline_enable(t,
127                                         (struct thread_pipeline_enable_msg_req *) req);
128                         thread_msg_send(t->msgq_out, rsp);
129                         break;
130                 }
131
132                 case THREAD_MSG_REQ_PIPELINE_DISABLE: {
133                         rsp->status = thread_pipeline_disable(t,
134                                         (struct thread_pipeline_disable_msg_req *) req);
135                         thread_msg_send(t->msgq_out, rsp);
136                         break;
137                 }
138
139                 case THREAD_MSG_REQ_HEADROOM_READ: {
140                         struct thread_headroom_read_msg_rsp *rsp =
141                                 (struct thread_headroom_read_msg_rsp *)
142                                 req;
143
144                         rsp->headroom_ratio = t->headroom_ratio;
145                         rsp->status = 0;
146                         thread_msg_send(t->msgq_out, rsp);
147                         break;
148                 }
149                 default:
150                         break;
151                 }
152
153         return 0;
154 }
155
156 static void
157 thread_headroom_update(struct app_thread_data *t, uint64_t time)
158 {
159         uint64_t time_diff = time - t->headroom_time;
160
161         t->headroom_ratio =
162                 ((double) t->headroom_cycles) / ((double) time_diff);
163
164         t->headroom_cycles = 0;
165         t->headroom_time = rte_rdtsc_precise();
166 }
167
168 int
169 app_thread(void *arg)
170 {
171         struct app_params *app = (struct app_params *) arg;
172         uint32_t core_id = rte_lcore_id(), i, j;
173         struct app_thread_data *t = &app->thread_data[core_id];
174
175         for (i = 0; ; i++) {
176                 uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular));
177                 uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom));
178
179                 /* Timer */
180                 if ((i & 0xF) == 0) {
181                         uint64_t time = rte_get_tsc_cycles();
182                         uint64_t t_deadline = UINT64_MAX;
183
184                         if (time < t->deadline)
185                                 continue;
186
187                         /* Timer for regular pipelines */
188                         for (j = 0; j < n_regular; j++) {
189                                 struct app_thread_pipeline_data *data =
190                                         &t->regular[j];
191                                 uint64_t p_deadline = data->deadline;
192
193                                 if (p_deadline <= time) {
194                                         data->f_timer(data->be);
195                                         p_deadline = time + data->timer_period;
196                                         data->deadline = p_deadline;
197                                 }
198
199                                 if (p_deadline < t_deadline)
200                                         t_deadline = p_deadline;
201                         }
202
203                         /* Timer for custom pipelines */
204                         for (j = 0; j < n_custom; j++) {
205                                 struct app_thread_pipeline_data *data =
206                                         &t->custom[j];
207                                 uint64_t p_deadline = data->deadline;
208
209                                 if (p_deadline <= time) {
210                                         data->f_timer(data->be);
211                                         p_deadline = time + data->timer_period;
212                                         data->deadline = p_deadline;
213                                 }
214
215                                 if (p_deadline < t_deadline)
216                                         t_deadline = p_deadline;
217                         }
218
219                         /* Timer for thread message request */
220                         {
221                                 uint64_t deadline = t->thread_req_deadline;
222
223                                 if (deadline <= time) {
224                                         thread_msg_req_handle(t);
225                                         thread_headroom_update(t, time);
226                                         deadline = time + t->timer_period;
227                                         t->thread_req_deadline = deadline;
228                                 }
229
230                                 if (deadline < t_deadline)
231                                         t_deadline = deadline;
232                         }
233
234
235                         t->deadline = t_deadline;
236                 }
237         }
238
239         return 0;
240 }