1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606 * Copyright(C) 2020 Marvell International Ltd.
3*2d9fd380Sjfb8856606 */
4*2d9fd380Sjfb8856606
5*2d9fd380Sjfb8856606 #ifndef _RTE_GRAPH_WORKER_H_
6*2d9fd380Sjfb8856606 #define _RTE_GRAPH_WORKER_H_
7*2d9fd380Sjfb8856606
8*2d9fd380Sjfb8856606 /**
9*2d9fd380Sjfb8856606 * @file rte_graph_worker.h
10*2d9fd380Sjfb8856606 *
11*2d9fd380Sjfb8856606 * @warning
12*2d9fd380Sjfb8856606 * @b EXPERIMENTAL:
13*2d9fd380Sjfb8856606 * All functions in this file may be changed or removed without prior notice.
14*2d9fd380Sjfb8856606 *
15*2d9fd380Sjfb8856606 * This API allows a worker thread to walk over a graph and nodes to create,
16*2d9fd380Sjfb8856606 * process, enqueue and move streams of objects to the next nodes.
17*2d9fd380Sjfb8856606 */
18*2d9fd380Sjfb8856606
19*2d9fd380Sjfb8856606 #include <rte_common.h>
20*2d9fd380Sjfb8856606 #include <rte_cycles.h>
21*2d9fd380Sjfb8856606 #include <rte_prefetch.h>
22*2d9fd380Sjfb8856606 #include <rte_memcpy.h>
23*2d9fd380Sjfb8856606 #include <rte_memory.h>
24*2d9fd380Sjfb8856606
25*2d9fd380Sjfb8856606 #include "rte_graph.h"
26*2d9fd380Sjfb8856606
27*2d9fd380Sjfb8856606 #ifdef __cplusplus
28*2d9fd380Sjfb8856606 extern "C" {
29*2d9fd380Sjfb8856606 #endif
30*2d9fd380Sjfb8856606
31*2d9fd380Sjfb8856606 /**
32*2d9fd380Sjfb8856606 * @internal
33*2d9fd380Sjfb8856606 *
34*2d9fd380Sjfb8856606 * Data structure to hold graph data.
35*2d9fd380Sjfb8856606 */
36*2d9fd380Sjfb8856606 struct rte_graph {
37*2d9fd380Sjfb8856606 uint32_t tail; /**< Tail of circular buffer. */
38*2d9fd380Sjfb8856606 uint32_t head; /**< Head of circular buffer. */
39*2d9fd380Sjfb8856606 uint32_t cir_mask; /**< Circular buffer wrap around mask. */
40*2d9fd380Sjfb8856606 rte_node_t nb_nodes; /**< Number of nodes in the graph. */
41*2d9fd380Sjfb8856606 rte_graph_off_t *cir_start; /**< Pointer to circular buffer. */
42*2d9fd380Sjfb8856606 rte_graph_off_t nodes_start; /**< Offset at which node memory starts. */
43*2d9fd380Sjfb8856606 rte_graph_t id; /**< Graph identifier. */
44*2d9fd380Sjfb8856606 int socket; /**< Socket ID where memory is allocated. */
45*2d9fd380Sjfb8856606 char name[RTE_GRAPH_NAMESIZE]; /**< Name of the graph. */
46*2d9fd380Sjfb8856606 uint64_t fence; /**< Fence. */
47*2d9fd380Sjfb8856606 } __rte_cache_aligned;
48*2d9fd380Sjfb8856606
49*2d9fd380Sjfb8856606 /**
50*2d9fd380Sjfb8856606 * @internal
51*2d9fd380Sjfb8856606 *
52*2d9fd380Sjfb8856606 * Data structure to hold node data.
53*2d9fd380Sjfb8856606 */
54*2d9fd380Sjfb8856606 struct rte_node {
55*2d9fd380Sjfb8856606 /* Slow path area */
56*2d9fd380Sjfb8856606 uint64_t fence; /**< Fence. */
57*2d9fd380Sjfb8856606 rte_graph_off_t next; /**< Index to next node. */
58*2d9fd380Sjfb8856606 rte_node_t id; /**< Node identifier. */
59*2d9fd380Sjfb8856606 rte_node_t parent_id; /**< Parent Node identifier. */
60*2d9fd380Sjfb8856606 rte_edge_t nb_edges; /**< Number of edges from this node. */
61*2d9fd380Sjfb8856606 uint32_t realloc_count; /**< Number of times realloced. */
62*2d9fd380Sjfb8856606
63*2d9fd380Sjfb8856606 char parent[RTE_NODE_NAMESIZE]; /**< Parent node name. */
64*2d9fd380Sjfb8856606 char name[RTE_NODE_NAMESIZE]; /**< Name of the node. */
65*2d9fd380Sjfb8856606
66*2d9fd380Sjfb8856606 /* Fast path area */
67*2d9fd380Sjfb8856606 #define RTE_NODE_CTX_SZ 16
68*2d9fd380Sjfb8856606 uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned; /**< Node Context. */
69*2d9fd380Sjfb8856606 uint16_t size; /**< Total number of objects available. */
70*2d9fd380Sjfb8856606 uint16_t idx; /**< Number of objects used. */
71*2d9fd380Sjfb8856606 rte_graph_off_t off; /**< Offset of node in the graph reel. */
72*2d9fd380Sjfb8856606 uint64_t total_cycles; /**< Cycles spent in this node. */
73*2d9fd380Sjfb8856606 uint64_t total_calls; /**< Calls done to this node. */
74*2d9fd380Sjfb8856606 uint64_t total_objs; /**< Objects processed by this node. */
75*2d9fd380Sjfb8856606 RTE_STD_C11
76*2d9fd380Sjfb8856606 union {
77*2d9fd380Sjfb8856606 void **objs; /**< Array of object pointers. */
78*2d9fd380Sjfb8856606 uint64_t objs_u64;
79*2d9fd380Sjfb8856606 };
80*2d9fd380Sjfb8856606 RTE_STD_C11
81*2d9fd380Sjfb8856606 union {
82*2d9fd380Sjfb8856606 rte_node_process_t process; /**< Process function. */
83*2d9fd380Sjfb8856606 uint64_t process_u64;
84*2d9fd380Sjfb8856606 };
85*2d9fd380Sjfb8856606 struct rte_node *nodes[] __rte_cache_min_aligned; /**< Next nodes. */
86*2d9fd380Sjfb8856606 } __rte_cache_aligned;
87*2d9fd380Sjfb8856606
88*2d9fd380Sjfb8856606 /**
89*2d9fd380Sjfb8856606 * @internal
90*2d9fd380Sjfb8856606 *
91*2d9fd380Sjfb8856606 * Allocate a stream of objects.
92*2d9fd380Sjfb8856606 *
93*2d9fd380Sjfb8856606 * If stream already exists then re-allocate it to a larger size.
94*2d9fd380Sjfb8856606 *
95*2d9fd380Sjfb8856606 * @param graph
96*2d9fd380Sjfb8856606 * Pointer to the graph object.
97*2d9fd380Sjfb8856606 * @param node
98*2d9fd380Sjfb8856606 * Pointer to the node object.
99*2d9fd380Sjfb8856606 */
100*2d9fd380Sjfb8856606 __rte_experimental
101*2d9fd380Sjfb8856606 void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
102*2d9fd380Sjfb8856606
103*2d9fd380Sjfb8856606 /**
104*2d9fd380Sjfb8856606 * @internal
105*2d9fd380Sjfb8856606 *
106*2d9fd380Sjfb8856606 * Allocate a stream with requested number of objects.
107*2d9fd380Sjfb8856606 *
108*2d9fd380Sjfb8856606 * If stream already exists then re-allocate it to a larger size.
109*2d9fd380Sjfb8856606 *
110*2d9fd380Sjfb8856606 * @param graph
111*2d9fd380Sjfb8856606 * Pointer to the graph object.
112*2d9fd380Sjfb8856606 * @param node
113*2d9fd380Sjfb8856606 * Pointer to the node object.
114*2d9fd380Sjfb8856606 * @param req_size
115*2d9fd380Sjfb8856606 * Number of objects to be allocated.
116*2d9fd380Sjfb8856606 */
117*2d9fd380Sjfb8856606 __rte_experimental
118*2d9fd380Sjfb8856606 void __rte_node_stream_alloc_size(struct rte_graph *graph,
119*2d9fd380Sjfb8856606 struct rte_node *node, uint16_t req_size);
120*2d9fd380Sjfb8856606
121*2d9fd380Sjfb8856606 /**
122*2d9fd380Sjfb8856606 * Perform graph walk on the circular buffer and invoke the process function
123*2d9fd380Sjfb8856606 * of the nodes and collect the stats.
124*2d9fd380Sjfb8856606 *
125*2d9fd380Sjfb8856606 * @param graph
126*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup function.
127*2d9fd380Sjfb8856606 *
128*2d9fd380Sjfb8856606 * @see rte_graph_lookup()
129*2d9fd380Sjfb8856606 */
130*2d9fd380Sjfb8856606 __rte_experimental
131*2d9fd380Sjfb8856606 static inline void
rte_graph_walk(struct rte_graph * graph)132*2d9fd380Sjfb8856606 rte_graph_walk(struct rte_graph *graph)
133*2d9fd380Sjfb8856606 {
134*2d9fd380Sjfb8856606 const rte_graph_off_t *cir_start = graph->cir_start;
135*2d9fd380Sjfb8856606 const rte_node_t mask = graph->cir_mask;
136*2d9fd380Sjfb8856606 uint32_t head = graph->head;
137*2d9fd380Sjfb8856606 struct rte_node *node;
138*2d9fd380Sjfb8856606 uint64_t start;
139*2d9fd380Sjfb8856606 uint16_t rc;
140*2d9fd380Sjfb8856606 void **objs;
141*2d9fd380Sjfb8856606
142*2d9fd380Sjfb8856606 /*
143*2d9fd380Sjfb8856606 * Walk on the source node(s) ((cir_start - head) -> cir_start) and then
144*2d9fd380Sjfb8856606 * on the pending streams (cir_start -> (cir_start + mask) -> cir_start)
145*2d9fd380Sjfb8856606 * in a circular buffer fashion.
146*2d9fd380Sjfb8856606 *
147*2d9fd380Sjfb8856606 * +-----+ <= cir_start - head [number of source nodes]
148*2d9fd380Sjfb8856606 * | |
149*2d9fd380Sjfb8856606 * | ... | <= source nodes
150*2d9fd380Sjfb8856606 * | |
151*2d9fd380Sjfb8856606 * +-----+ <= cir_start [head = 0] [tail = 0]
152*2d9fd380Sjfb8856606 * | |
153*2d9fd380Sjfb8856606 * | ... | <= pending streams
154*2d9fd380Sjfb8856606 * | |
155*2d9fd380Sjfb8856606 * +-----+ <= cir_start + mask
156*2d9fd380Sjfb8856606 */
157*2d9fd380Sjfb8856606 while (likely(head != graph->tail)) {
158*2d9fd380Sjfb8856606 node = RTE_PTR_ADD(graph, cir_start[(int32_t)head++]);
159*2d9fd380Sjfb8856606 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
160*2d9fd380Sjfb8856606 objs = node->objs;
161*2d9fd380Sjfb8856606 rte_prefetch0(objs);
162*2d9fd380Sjfb8856606
163*2d9fd380Sjfb8856606 if (rte_graph_has_stats_feature()) {
164*2d9fd380Sjfb8856606 start = rte_rdtsc();
165*2d9fd380Sjfb8856606 rc = node->process(graph, node, objs, node->idx);
166*2d9fd380Sjfb8856606 node->total_cycles += rte_rdtsc() - start;
167*2d9fd380Sjfb8856606 node->total_calls++;
168*2d9fd380Sjfb8856606 node->total_objs += rc;
169*2d9fd380Sjfb8856606 } else {
170*2d9fd380Sjfb8856606 node->process(graph, node, objs, node->idx);
171*2d9fd380Sjfb8856606 }
172*2d9fd380Sjfb8856606 node->idx = 0;
173*2d9fd380Sjfb8856606 head = likely((int32_t)head > 0) ? head & mask : head;
174*2d9fd380Sjfb8856606 }
175*2d9fd380Sjfb8856606 graph->tail = 0;
176*2d9fd380Sjfb8856606 }
177*2d9fd380Sjfb8856606
178*2d9fd380Sjfb8856606 /* Fast path helper functions */
179*2d9fd380Sjfb8856606
180*2d9fd380Sjfb8856606 /**
181*2d9fd380Sjfb8856606 * @internal
182*2d9fd380Sjfb8856606 *
183*2d9fd380Sjfb8856606 * Enqueue a given node to the tail of the graph reel.
184*2d9fd380Sjfb8856606 *
185*2d9fd380Sjfb8856606 * @param graph
186*2d9fd380Sjfb8856606 * Pointer Graph object.
187*2d9fd380Sjfb8856606 * @param node
188*2d9fd380Sjfb8856606 * Pointer to node object to be enqueued.
189*2d9fd380Sjfb8856606 */
190*2d9fd380Sjfb8856606 static __rte_always_inline void
__rte_node_enqueue_tail_update(struct rte_graph * graph,struct rte_node * node)191*2d9fd380Sjfb8856606 __rte_node_enqueue_tail_update(struct rte_graph *graph, struct rte_node *node)
192*2d9fd380Sjfb8856606 {
193*2d9fd380Sjfb8856606 uint32_t tail;
194*2d9fd380Sjfb8856606
195*2d9fd380Sjfb8856606 tail = graph->tail;
196*2d9fd380Sjfb8856606 graph->cir_start[tail++] = node->off;
197*2d9fd380Sjfb8856606 graph->tail = tail & graph->cir_mask;
198*2d9fd380Sjfb8856606 }
199*2d9fd380Sjfb8856606
200*2d9fd380Sjfb8856606 /**
201*2d9fd380Sjfb8856606 * @internal
202*2d9fd380Sjfb8856606 *
203*2d9fd380Sjfb8856606 * Enqueue sequence prologue function.
204*2d9fd380Sjfb8856606 *
205*2d9fd380Sjfb8856606 * Updates the node to tail of graph reel and resizes the number of objects
206*2d9fd380Sjfb8856606 * available in the stream as needed.
207*2d9fd380Sjfb8856606 *
208*2d9fd380Sjfb8856606 * @param graph
209*2d9fd380Sjfb8856606 * Pointer to the graph object.
210*2d9fd380Sjfb8856606 * @param node
211*2d9fd380Sjfb8856606 * Pointer to the node object.
212*2d9fd380Sjfb8856606 * @param idx
213*2d9fd380Sjfb8856606 * Index at which the object enqueue starts from.
214*2d9fd380Sjfb8856606 * @param space
215*2d9fd380Sjfb8856606 * Space required for the object enqueue.
216*2d9fd380Sjfb8856606 */
217*2d9fd380Sjfb8856606 static __rte_always_inline void
__rte_node_enqueue_prologue(struct rte_graph * graph,struct rte_node * node,const uint16_t idx,const uint16_t space)218*2d9fd380Sjfb8856606 __rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
219*2d9fd380Sjfb8856606 const uint16_t idx, const uint16_t space)
220*2d9fd380Sjfb8856606 {
221*2d9fd380Sjfb8856606
222*2d9fd380Sjfb8856606 /* Add to the pending stream list if the node is new */
223*2d9fd380Sjfb8856606 if (idx == 0)
224*2d9fd380Sjfb8856606 __rte_node_enqueue_tail_update(graph, node);
225*2d9fd380Sjfb8856606
226*2d9fd380Sjfb8856606 if (unlikely(node->size < (idx + space)))
227*2d9fd380Sjfb8856606 __rte_node_stream_alloc(graph, node);
228*2d9fd380Sjfb8856606 }
229*2d9fd380Sjfb8856606
230*2d9fd380Sjfb8856606 /**
231*2d9fd380Sjfb8856606 * @internal
232*2d9fd380Sjfb8856606 *
233*2d9fd380Sjfb8856606 * Get the node pointer from current node edge id.
234*2d9fd380Sjfb8856606 *
235*2d9fd380Sjfb8856606 * @param node
236*2d9fd380Sjfb8856606 * Current node pointer.
237*2d9fd380Sjfb8856606 * @param next
238*2d9fd380Sjfb8856606 * Edge id of the required node.
239*2d9fd380Sjfb8856606 *
240*2d9fd380Sjfb8856606 * @return
241*2d9fd380Sjfb8856606 * Pointer to the node denoted by the edge id.
242*2d9fd380Sjfb8856606 */
243*2d9fd380Sjfb8856606 static __rte_always_inline struct rte_node *
__rte_node_next_node_get(struct rte_node * node,rte_edge_t next)244*2d9fd380Sjfb8856606 __rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
245*2d9fd380Sjfb8856606 {
246*2d9fd380Sjfb8856606 RTE_ASSERT(next < node->nb_edges);
247*2d9fd380Sjfb8856606 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
248*2d9fd380Sjfb8856606 node = node->nodes[next];
249*2d9fd380Sjfb8856606 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
250*2d9fd380Sjfb8856606
251*2d9fd380Sjfb8856606 return node;
252*2d9fd380Sjfb8856606 }
253*2d9fd380Sjfb8856606
254*2d9fd380Sjfb8856606 /**
255*2d9fd380Sjfb8856606 * Enqueue the objs to next node for further processing and set
256*2d9fd380Sjfb8856606 * the next node to pending state in the circular buffer.
257*2d9fd380Sjfb8856606 *
258*2d9fd380Sjfb8856606 * @param graph
259*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
260*2d9fd380Sjfb8856606 * @param node
261*2d9fd380Sjfb8856606 * Current node pointer.
262*2d9fd380Sjfb8856606 * @param next
263*2d9fd380Sjfb8856606 * Relative next node index to enqueue objs.
264*2d9fd380Sjfb8856606 * @param objs
265*2d9fd380Sjfb8856606 * Objs to enqueue.
266*2d9fd380Sjfb8856606 * @param nb_objs
267*2d9fd380Sjfb8856606 * Number of objs to enqueue.
268*2d9fd380Sjfb8856606 */
269*2d9fd380Sjfb8856606 __rte_experimental
270*2d9fd380Sjfb8856606 static inline void
rte_node_enqueue(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,void ** objs,uint16_t nb_objs)271*2d9fd380Sjfb8856606 rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
272*2d9fd380Sjfb8856606 rte_edge_t next, void **objs, uint16_t nb_objs)
273*2d9fd380Sjfb8856606 {
274*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
275*2d9fd380Sjfb8856606 const uint16_t idx = node->idx;
276*2d9fd380Sjfb8856606
277*2d9fd380Sjfb8856606 __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
278*2d9fd380Sjfb8856606
279*2d9fd380Sjfb8856606 rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
280*2d9fd380Sjfb8856606 node->idx = idx + nb_objs;
281*2d9fd380Sjfb8856606 }
282*2d9fd380Sjfb8856606
283*2d9fd380Sjfb8856606 /**
284*2d9fd380Sjfb8856606 * Enqueue only one obj to next node for further processing and
285*2d9fd380Sjfb8856606 * set the next node to pending state in the circular buffer.
286*2d9fd380Sjfb8856606 *
287*2d9fd380Sjfb8856606 * @param graph
288*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
289*2d9fd380Sjfb8856606 * @param node
290*2d9fd380Sjfb8856606 * Current node pointer.
291*2d9fd380Sjfb8856606 * @param next
292*2d9fd380Sjfb8856606 * Relative next node index to enqueue objs.
293*2d9fd380Sjfb8856606 * @param obj
294*2d9fd380Sjfb8856606 * Obj to enqueue.
295*2d9fd380Sjfb8856606 */
296*2d9fd380Sjfb8856606 __rte_experimental
297*2d9fd380Sjfb8856606 static inline void
rte_node_enqueue_x1(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,void * obj)298*2d9fd380Sjfb8856606 rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
299*2d9fd380Sjfb8856606 rte_edge_t next, void *obj)
300*2d9fd380Sjfb8856606 {
301*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
302*2d9fd380Sjfb8856606 uint16_t idx = node->idx;
303*2d9fd380Sjfb8856606
304*2d9fd380Sjfb8856606 __rte_node_enqueue_prologue(graph, node, idx, 1);
305*2d9fd380Sjfb8856606
306*2d9fd380Sjfb8856606 node->objs[idx++] = obj;
307*2d9fd380Sjfb8856606 node->idx = idx;
308*2d9fd380Sjfb8856606 }
309*2d9fd380Sjfb8856606
310*2d9fd380Sjfb8856606 /**
311*2d9fd380Sjfb8856606 * Enqueue only two objs to next node for further processing and
312*2d9fd380Sjfb8856606 * set the next node to pending state in the circular buffer.
313*2d9fd380Sjfb8856606 * Same as rte_node_enqueue_x1 but enqueue two objs.
314*2d9fd380Sjfb8856606 *
315*2d9fd380Sjfb8856606 * @param graph
316*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
317*2d9fd380Sjfb8856606 * @param node
318*2d9fd380Sjfb8856606 * Current node pointer.
319*2d9fd380Sjfb8856606 * @param next
320*2d9fd380Sjfb8856606 * Relative next node index to enqueue objs.
321*2d9fd380Sjfb8856606 * @param obj0
322*2d9fd380Sjfb8856606 * Obj to enqueue.
323*2d9fd380Sjfb8856606 * @param obj1
324*2d9fd380Sjfb8856606 * Obj to enqueue.
325*2d9fd380Sjfb8856606 */
326*2d9fd380Sjfb8856606 __rte_experimental
327*2d9fd380Sjfb8856606 static inline void
rte_node_enqueue_x2(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,void * obj0,void * obj1)328*2d9fd380Sjfb8856606 rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
329*2d9fd380Sjfb8856606 rte_edge_t next, void *obj0, void *obj1)
330*2d9fd380Sjfb8856606 {
331*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
332*2d9fd380Sjfb8856606 uint16_t idx = node->idx;
333*2d9fd380Sjfb8856606
334*2d9fd380Sjfb8856606 __rte_node_enqueue_prologue(graph, node, idx, 2);
335*2d9fd380Sjfb8856606
336*2d9fd380Sjfb8856606 node->objs[idx++] = obj0;
337*2d9fd380Sjfb8856606 node->objs[idx++] = obj1;
338*2d9fd380Sjfb8856606 node->idx = idx;
339*2d9fd380Sjfb8856606 }
340*2d9fd380Sjfb8856606
341*2d9fd380Sjfb8856606 /**
342*2d9fd380Sjfb8856606 * Enqueue only four objs to next node for further processing and
343*2d9fd380Sjfb8856606 * set the next node to pending state in the circular buffer.
344*2d9fd380Sjfb8856606 * Same as rte_node_enqueue_x1 but enqueue four objs.
345*2d9fd380Sjfb8856606 *
346*2d9fd380Sjfb8856606 * @param graph
347*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
348*2d9fd380Sjfb8856606 * @param node
349*2d9fd380Sjfb8856606 * Current node pointer.
350*2d9fd380Sjfb8856606 * @param next
351*2d9fd380Sjfb8856606 * Relative next node index to enqueue objs.
352*2d9fd380Sjfb8856606 * @param obj0
353*2d9fd380Sjfb8856606 * 1st obj to enqueue.
354*2d9fd380Sjfb8856606 * @param obj1
355*2d9fd380Sjfb8856606 * 2nd obj to enqueue.
356*2d9fd380Sjfb8856606 * @param obj2
357*2d9fd380Sjfb8856606 * 3rd obj to enqueue.
358*2d9fd380Sjfb8856606 * @param obj3
359*2d9fd380Sjfb8856606 * 4th obj to enqueue.
360*2d9fd380Sjfb8856606 */
361*2d9fd380Sjfb8856606 __rte_experimental
362*2d9fd380Sjfb8856606 static inline void
rte_node_enqueue_x4(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,void * obj0,void * obj1,void * obj2,void * obj3)363*2d9fd380Sjfb8856606 rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
364*2d9fd380Sjfb8856606 rte_edge_t next, void *obj0, void *obj1, void *obj2,
365*2d9fd380Sjfb8856606 void *obj3)
366*2d9fd380Sjfb8856606 {
367*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
368*2d9fd380Sjfb8856606 uint16_t idx = node->idx;
369*2d9fd380Sjfb8856606
370*2d9fd380Sjfb8856606 __rte_node_enqueue_prologue(graph, node, idx, 4);
371*2d9fd380Sjfb8856606
372*2d9fd380Sjfb8856606 node->objs[idx++] = obj0;
373*2d9fd380Sjfb8856606 node->objs[idx++] = obj1;
374*2d9fd380Sjfb8856606 node->objs[idx++] = obj2;
375*2d9fd380Sjfb8856606 node->objs[idx++] = obj3;
376*2d9fd380Sjfb8856606 node->idx = idx;
377*2d9fd380Sjfb8856606 }
378*2d9fd380Sjfb8856606
379*2d9fd380Sjfb8856606 /**
380*2d9fd380Sjfb8856606 * Enqueue objs to multiple next nodes for further processing and
381*2d9fd380Sjfb8856606 * set the next nodes to pending state in the circular buffer.
382*2d9fd380Sjfb8856606 * objs[i] will be enqueued to nexts[i].
383*2d9fd380Sjfb8856606 *
384*2d9fd380Sjfb8856606 * @param graph
385*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
386*2d9fd380Sjfb8856606 * @param node
387*2d9fd380Sjfb8856606 * Current node pointer.
388*2d9fd380Sjfb8856606 * @param nexts
389*2d9fd380Sjfb8856606 * List of relative next node indices to enqueue objs.
390*2d9fd380Sjfb8856606 * @param objs
391*2d9fd380Sjfb8856606 * List of objs to enqueue.
392*2d9fd380Sjfb8856606 * @param nb_objs
393*2d9fd380Sjfb8856606 * Number of objs to enqueue.
394*2d9fd380Sjfb8856606 */
395*2d9fd380Sjfb8856606 __rte_experimental
396*2d9fd380Sjfb8856606 static inline void
rte_node_enqueue_next(struct rte_graph * graph,struct rte_node * node,rte_edge_t * nexts,void ** objs,uint16_t nb_objs)397*2d9fd380Sjfb8856606 rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
398*2d9fd380Sjfb8856606 rte_edge_t *nexts, void **objs, uint16_t nb_objs)
399*2d9fd380Sjfb8856606 {
400*2d9fd380Sjfb8856606 uint16_t i;
401*2d9fd380Sjfb8856606
402*2d9fd380Sjfb8856606 for (i = 0; i < nb_objs; i++)
403*2d9fd380Sjfb8856606 rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
404*2d9fd380Sjfb8856606 }
405*2d9fd380Sjfb8856606
406*2d9fd380Sjfb8856606 /**
407*2d9fd380Sjfb8856606 * Get the stream of next node to enqueue the objs.
408*2d9fd380Sjfb8856606 * Once done with the updating the objs, needs to call
409*2d9fd380Sjfb8856606 * rte_node_next_stream_put to put the next node to pending state.
410*2d9fd380Sjfb8856606 *
411*2d9fd380Sjfb8856606 * @param graph
412*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
413*2d9fd380Sjfb8856606 * @param node
414*2d9fd380Sjfb8856606 * Current node pointer.
415*2d9fd380Sjfb8856606 * @param next
416*2d9fd380Sjfb8856606 * Relative next node index to get stream.
417*2d9fd380Sjfb8856606 * @param nb_objs
418*2d9fd380Sjfb8856606 * Requested free size of the next stream.
419*2d9fd380Sjfb8856606 *
420*2d9fd380Sjfb8856606 * @return
421*2d9fd380Sjfb8856606 * Valid next stream on success.
422*2d9fd380Sjfb8856606 *
423*2d9fd380Sjfb8856606 * @see rte_node_next_stream_put().
424*2d9fd380Sjfb8856606 */
425*2d9fd380Sjfb8856606 __rte_experimental
426*2d9fd380Sjfb8856606 static inline void **
rte_node_next_stream_get(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,uint16_t nb_objs)427*2d9fd380Sjfb8856606 rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
428*2d9fd380Sjfb8856606 rte_edge_t next, uint16_t nb_objs)
429*2d9fd380Sjfb8856606 {
430*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
431*2d9fd380Sjfb8856606 const uint16_t idx = node->idx;
432*2d9fd380Sjfb8856606 uint16_t free_space = node->size - idx;
433*2d9fd380Sjfb8856606
434*2d9fd380Sjfb8856606 if (unlikely(free_space < nb_objs))
435*2d9fd380Sjfb8856606 __rte_node_stream_alloc_size(graph, node, nb_objs);
436*2d9fd380Sjfb8856606
437*2d9fd380Sjfb8856606 return &node->objs[idx];
438*2d9fd380Sjfb8856606 }
439*2d9fd380Sjfb8856606
440*2d9fd380Sjfb8856606 /**
441*2d9fd380Sjfb8856606 * Put the next stream to pending state in the circular buffer
442*2d9fd380Sjfb8856606 * for further processing. Should be invoked after rte_node_next_stream_get().
443*2d9fd380Sjfb8856606 *
444*2d9fd380Sjfb8856606 * @param graph
445*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
446*2d9fd380Sjfb8856606 * @param node
447*2d9fd380Sjfb8856606 * Current node pointer.
448*2d9fd380Sjfb8856606 * @param next
449*2d9fd380Sjfb8856606 * Relative next node index..
450*2d9fd380Sjfb8856606 * @param idx
451*2d9fd380Sjfb8856606 * Number of objs updated in the stream after getting the stream using
452*2d9fd380Sjfb8856606 * rte_node_next_stream_get.
453*2d9fd380Sjfb8856606 *
454*2d9fd380Sjfb8856606 * @see rte_node_next_stream_get().
455*2d9fd380Sjfb8856606 */
456*2d9fd380Sjfb8856606 __rte_experimental
457*2d9fd380Sjfb8856606 static inline void
rte_node_next_stream_put(struct rte_graph * graph,struct rte_node * node,rte_edge_t next,uint16_t idx)458*2d9fd380Sjfb8856606 rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
459*2d9fd380Sjfb8856606 rte_edge_t next, uint16_t idx)
460*2d9fd380Sjfb8856606 {
461*2d9fd380Sjfb8856606 if (unlikely(!idx))
462*2d9fd380Sjfb8856606 return;
463*2d9fd380Sjfb8856606
464*2d9fd380Sjfb8856606 node = __rte_node_next_node_get(node, next);
465*2d9fd380Sjfb8856606 if (node->idx == 0)
466*2d9fd380Sjfb8856606 __rte_node_enqueue_tail_update(graph, node);
467*2d9fd380Sjfb8856606
468*2d9fd380Sjfb8856606 node->idx += idx;
469*2d9fd380Sjfb8856606 }
470*2d9fd380Sjfb8856606
471*2d9fd380Sjfb8856606 /**
472*2d9fd380Sjfb8856606 * Home run scenario, Enqueue all the objs of current node to next
473*2d9fd380Sjfb8856606 * node in optimized way by swapping the streams of both nodes.
474*2d9fd380Sjfb8856606 * Performs good when next node is already not in pending state.
475*2d9fd380Sjfb8856606 * If next node is already in pending state then normal enqueue
476*2d9fd380Sjfb8856606 * will be used.
477*2d9fd380Sjfb8856606 *
478*2d9fd380Sjfb8856606 * @param graph
479*2d9fd380Sjfb8856606 * Graph pointer returned from rte_graph_lookup().
480*2d9fd380Sjfb8856606 * @param src
481*2d9fd380Sjfb8856606 * Current node pointer.
482*2d9fd380Sjfb8856606 * @param next
483*2d9fd380Sjfb8856606 * Relative next node index.
484*2d9fd380Sjfb8856606 */
485*2d9fd380Sjfb8856606 __rte_experimental
486*2d9fd380Sjfb8856606 static inline void
rte_node_next_stream_move(struct rte_graph * graph,struct rte_node * src,rte_edge_t next)487*2d9fd380Sjfb8856606 rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
488*2d9fd380Sjfb8856606 rte_edge_t next)
489*2d9fd380Sjfb8856606 {
490*2d9fd380Sjfb8856606 struct rte_node *dst = __rte_node_next_node_get(src, next);
491*2d9fd380Sjfb8856606
492*2d9fd380Sjfb8856606 /* Let swap the pointers if dst don't have valid objs */
493*2d9fd380Sjfb8856606 if (likely(dst->idx == 0)) {
494*2d9fd380Sjfb8856606 void **dobjs = dst->objs;
495*2d9fd380Sjfb8856606 uint16_t dsz = dst->size;
496*2d9fd380Sjfb8856606 dst->objs = src->objs;
497*2d9fd380Sjfb8856606 dst->size = src->size;
498*2d9fd380Sjfb8856606 src->objs = dobjs;
499*2d9fd380Sjfb8856606 src->size = dsz;
500*2d9fd380Sjfb8856606 dst->idx = src->idx;
501*2d9fd380Sjfb8856606 __rte_node_enqueue_tail_update(graph, dst);
502*2d9fd380Sjfb8856606 } else { /* Move the objects from src node to dst node */
503*2d9fd380Sjfb8856606 rte_node_enqueue(graph, src, next, src->objs, src->idx);
504*2d9fd380Sjfb8856606 }
505*2d9fd380Sjfb8856606 }
506*2d9fd380Sjfb8856606
507*2d9fd380Sjfb8856606 #ifdef __cplusplus
508*2d9fd380Sjfb8856606 }
509*2d9fd380Sjfb8856606 #endif
510*2d9fd380Sjfb8856606
511*2d9fd380Sjfb8856606 #endif /* _RTE_GRAPH_WORKER_H_ */
512