CNDP  22.08.0
cne_graph_worker.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2020 Marvell International Ltd.
3  */
4 
5 #ifndef _CNE_GRAPH_WORKER_H_
6 #define _CNE_GRAPH_WORKER_H_
7 
15 #include <string.h>
16 #include <cne_common.h>
17 #include <cne_cycles.h>
18 #include <cne_prefetch.h>
19 #include <cne_branch_prediction.h>
20 #include <cne_log.h>
21 
22 #include "cne_graph.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
33 struct cne_graph {
34  uint32_t tail;
35  uint32_t head;
36  uint32_t cir_mask;
37  cne_node_t nb_nodes;
38  cne_graph_off_t *cir_start;
39  cne_graph_off_t nodes_start;
40  cne_graph_t id;
41  char name[CNE_GRAPH_NAMESIZE];
42  uint64_t fence;
43 } __cne_cache_aligned;
44 
50 struct cne_node {
51  /* Slow path area */
52  uint64_t fence;
53  cne_graph_off_t next;
54  cne_node_t id;
55  cne_node_t parent_id;
56  cne_edge_t nb_edges;
57  uint32_t realloc_count;
59  char parent[CNE_NODE_NAMESIZE];
60  char name[CNE_NODE_NAMESIZE];
62  /* Fast path area */
63 #define CNE_NODE_CTX_SZ 16
64  uint8_t ctx[CNE_NODE_CTX_SZ] __cne_cache_aligned;
65  uint16_t size;
66  uint16_t idx;
67  cne_graph_off_t off;
68  uint64_t total_cycles;
69  uint64_t total_calls;
70  uint64_t total_objs;
72  union {
73  void **objs;
74  uint64_t objs_u64;
75  };
77  union {
78  cne_node_process_t process;
79  uint64_t process_u64;
80  };
81  struct cne_node *nodes[] __cne_cache_min_aligned;
82 } __cne_cache_aligned;
83 
96 void __cne_node_stream_alloc(struct cne_graph *graph, struct cne_node *node);
97 
112 void __cne_node_stream_alloc_size(struct cne_graph *graph, struct cne_node *node,
113  uint16_t req_size);
114 
124 static inline void
125 cne_graph_walk(struct cne_graph *graph)
126 {
127  const cne_graph_off_t *cir_start = graph->cir_start;
128  const cne_node_t mask = graph->cir_mask;
129  uint32_t head = graph->head;
130  struct cne_node *node;
131  uint64_t start;
132  uint16_t rc;
133  void **objs;
134 
135  /*
136  * Walk on the source node(s) ((cir_start - head) -> cir_start) and then
137  * on the pending streams (cir_start -> (cir_start + mask) -> cir_start)
138  * in a circular buffer fashion.
139  *
140  * +-----+ <= cir_start - head [number of source nodes]
141  * | |
142  * | ... | <= source nodes
143  * | |
144  * +-----+ <= cir_start [head = 0] [tail = 0]
145  * | |
146  * | ... | <= pending streams
147  * | |
148  * +-----+ <= cir_start + mask
149  */
150  while (likely(head != graph->tail)) {
151  node = CNE_PTR_ADD(graph, cir_start[(int32_t)head++]);
152  CNE_ASSERT(node->fence == CNE_GRAPH_FENCE);
153  objs = node->objs;
154  cne_prefetch0(objs);
155 
157  start = cne_rdtsc();
158  rc = node->process(graph, node, objs, node->idx);
159  node->total_cycles += cne_rdtsc() - start;
160  node->total_calls++;
161  node->total_objs += rc;
162  } else
163  node->process(graph, node, objs, node->idx);
164  node->idx = 0;
165  head = likely((int32_t)head > 0) ? head & mask : head;
166  }
167  graph->tail = 0;
168 }
169 
170 /* Fast path helper functions */
171 
182 static __cne_always_inline void
183 __cne_node_enqueue_tail_update(struct cne_graph *graph, struct cne_node *node)
184 {
185  uint32_t tail;
186 
187  tail = graph->tail;
188  graph->cir_start[tail++] = node->off;
189  graph->tail = tail & graph->cir_mask;
190 }
191 
209 static __cne_always_inline void
210 __cne_node_enqueue_prologue(struct cne_graph *graph, struct cne_node *node, const uint16_t idx,
211  const uint16_t space)
212 {
213  /* Add to the pending stream list if the node is new */
214  if (idx == 0)
215  __cne_node_enqueue_tail_update(graph, node);
216 
217  if (unlikely(node->size < (idx + space)))
218  __cne_node_stream_alloc_size(graph, node, node->size + space);
219 }
220 
234 static __cne_always_inline struct cne_node *
235 __cne_node_next_node_get(struct cne_node *node, cne_edge_t next)
236 {
237  CNE_ASSERT(next < node->nb_edges);
238  CNE_ASSERT(node->fence == CNE_GRAPH_FENCE);
239  node = node->nodes[next];
240  CNE_ASSERT(node->fence == CNE_GRAPH_FENCE);
241 
242  return node;
243 }
244 
259 static inline void
260 cne_node_add_objects_to_source(struct cne_graph *graph, struct cne_node *node, void **objs,
261  uint16_t nb_objs)
262 {
263  const uint16_t idx = node->idx;
264 
265  if (unlikely(node->size < (idx + nb_objs)))
266  __cne_node_stream_alloc(graph, node);
267 
268  memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
269  node->idx = idx + nb_objs;
270 }
283 static inline void
284 cne_node_add_objects_to_input(struct cne_graph *graph, struct cne_node *node, void **objs,
285  uint16_t nb_objs)
286 {
287  const uint16_t idx = node->idx;
288 
289  __cne_node_enqueue_prologue(graph, node, idx, nb_objs);
290 
291  memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
292  node->idx = idx + nb_objs;
293 }
294 
310 static inline void
311 cne_node_enqueue(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void **objs,
312  uint16_t nb_objs)
313 {
314  node = __cne_node_next_node_get(node, next);
315  const uint16_t idx = node->idx;
316 
317  __cne_node_enqueue_prologue(graph, node, idx, nb_objs);
318 
319  memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
320  node->idx = idx + nb_objs;
321 }
322 
336 static inline void
337 cne_node_enqueue_x1(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj)
338 {
339  node = __cne_node_next_node_get(node, next);
340  uint16_t idx = node->idx;
341 
342  __cne_node_enqueue_prologue(graph, node, idx, 1);
343 
344  node->objs[idx++] = obj;
345  node->idx = idx;
346 }
347 
364 static inline void
365 cne_node_enqueue_x2(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj0,
366  void *obj1)
367 {
368  node = __cne_node_next_node_get(node, next);
369  uint16_t idx = node->idx;
370 
371  __cne_node_enqueue_prologue(graph, node, idx, 2);
372 
373  node->objs[idx++] = obj0;
374  node->objs[idx++] = obj1;
375  node->idx = idx;
376 }
377 
398 static inline void
399 cne_node_enqueue_x4(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj0,
400  void *obj1, void *obj2, void *obj3)
401 {
402  node = __cne_node_next_node_get(node, next);
403  uint16_t idx = node->idx;
404 
405  __cne_node_enqueue_prologue(graph, node, idx, 4);
406 
407  node->objs[idx++] = obj0;
408  node->objs[idx++] = obj1;
409  node->objs[idx++] = obj2;
410  node->objs[idx++] = obj3;
411  node->idx = idx;
412 }
413 
430 static inline void
431 cne_node_enqueue_next(struct cne_graph *graph, struct cne_node *node, cne_edge_t *nexts,
432  void **objs, uint16_t nb_objs)
433 {
434  uint16_t i;
435 
436  for (i = 0; i < nb_objs; i++)
437  cne_node_enqueue_x1(graph, node, nexts[i], objs[i]);
438 }
439 
459 static inline void **
460 cne_node_next_stream_get(struct cne_graph *graph, struct cne_node *node, cne_edge_t next,
461  uint16_t nb_objs)
462 {
463  node = __cne_node_next_node_get(node, next);
464  const uint16_t idx = node->idx;
465  uint16_t free_space = node->size - idx;
466 
467  if (unlikely(free_space < nb_objs))
468  __cne_node_stream_alloc_size(graph, node, node->size + nb_objs);
469 
470  return &node->objs[idx];
471 }
472 
489 static inline void
490 cne_node_next_stream_put(struct cne_graph *graph, struct cne_node *node, cne_edge_t next,
491  uint16_t idx)
492 {
493  if (unlikely(!idx))
494  return;
495 
496  node = __cne_node_next_node_get(node, next);
497 
498  if (node->idx == 0)
499  __cne_node_enqueue_tail_update(graph, node);
500 
501  node->idx += idx;
502 }
503 
518 static inline void
519 cne_node_next_stream_move(struct cne_graph *graph, struct cne_node *src, cne_edge_t next)
520 {
521  struct cne_node *dst = __cne_node_next_node_get(src, next);
522 
523  CNE_DEBUG("Src %-16s', Dst '%-16s' next %d\n", src->name, dst->name, next);
524 
525  /* Swap the pointers if dst doesn't have valid objs */
526  if (likely(dst->idx == 0)) {
527  void **dobjs = dst->objs;
528  uint16_t dsz = dst->size;
529 
530  dst->objs = src->objs;
531  dst->size = src->size;
532  src->objs = dobjs;
533  src->size = dsz;
534  dst->idx = src->idx;
535 
536  __cne_node_enqueue_tail_update(graph, dst);
537  } else /* Move the objects from src node to dst node */
538  cne_node_enqueue(graph, src, next, src->objs, src->idx);
539 }
540 
541 #ifdef __cplusplus
542 }
543 #endif
544 
545 #endif /* _CNE_GRAPH_WORKER_H_ */
#define likely(x)
#define unlikely(x)
#define CNE_PTR_ADD(ptr, x)
Definition: cne_common.h:235
#define CNE_STD_C11
Definition: cne_common.h:91
#define __cne_cache_min_aligned
Definition: cne_common.h:382
#define __cne_always_inline
Definition: cne_common.h:218
static uint64_t cne_rdtsc(void)
Definition: cne_cycles.h:32
uint16_t(* cne_node_process_t)(struct cne_graph *graph, struct cne_node *node, void **objs, uint16_t nb_objs)
Definition: cne_graph.h:94
uint32_t cne_graph_off_t
Definition: cne_graph.h:39
uint32_t cne_node_t
Definition: cne_graph.h:40
static __cne_always_inline int cne_graph_has_stats_feature(void)
Definition: cne_graph.h:649
#define CNE_GRAPH_FENCE
Definition: cne_graph.h:37
uint16_t cne_edge_t
Definition: cne_graph.h:41
uint16_t cne_graph_t
Definition: cne_graph.h:42
#define CNE_NODE_NAMESIZE
Definition: cne_graph.h:32
#define CNE_GRAPH_NAMESIZE
Definition: cne_graph.h:31
static void cne_node_add_objects_to_source(struct cne_graph *graph, struct cne_node *node, void **objs, uint16_t nb_objs)
static void cne_node_enqueue_x4(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj0, void *obj1, void *obj2, void *obj3)
static void cne_node_next_stream_move(struct cne_graph *graph, struct cne_node *src, cne_edge_t next)
static void cne_node_enqueue(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void **objs, uint16_t nb_objs)
static void cne_node_enqueue_x2(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj0, void *obj1)
static void ** cne_node_next_stream_get(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, uint16_t nb_objs)
static void cne_node_add_objects_to_input(struct cne_graph *graph, struct cne_node *node, void **objs, uint16_t nb_objs)
static void cne_graph_walk(struct cne_graph *graph)
static void cne_node_enqueue_x1(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, void *obj)
static void cne_node_next_stream_put(struct cne_graph *graph, struct cne_node *node, cne_edge_t next, uint16_t idx)
static void cne_node_enqueue_next(struct cne_graph *graph, struct cne_node *node, cne_edge_t *nexts, void **objs, uint16_t nb_objs)
static void cne_prefetch0(const volatile void *p)
Definition: cne_prefetch.h:27