On 4/5/20 10:55 AM, jer...@marvell.com wrote:
> From: Jerin Jacob <jer...@marvell.com>
[...]
> diff --git a/lib/librte_graph/graph_populate.c 
> b/lib/librte_graph/graph_populate.c
> new file mode 100644
> index 000000000..093512efa
> --- /dev/null
> +++ b/lib/librte_graph/graph_populate.c
> @@ -0,0 +1,234 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#include <fnmatch.h>
> +#include <stdbool.h>
> +
> +#include <rte_common.h>
> +#include <rte_errno.h>
> +#include <rte_malloc.h>
> +#include <rte_memzone.h>
> +
> +#include "graph_private.h"
> +
> +static size_t
> +graph_fp_mem_calc_size(struct graph *graph)
> +{
> +     struct graph_node *graph_node;
> +     rte_node_t val;
> +     size_t sz;
> +
> +     /* Graph header */
> +     sz = sizeof(struct rte_graph);
> +     /* Source nodes list */
> +     sz += sizeof(rte_graph_off_t) * graph->src_node_count;
> +     /* Circular buffer for pending streams of size number of nodes */
> +     val = rte_align32pow2(graph->node_count * sizeof(rte_graph_off_t));
> +     sz = RTE_ALIGN(sz, val);
> +     graph->cir_start = sz;
> +     graph->cir_mask = rte_align32pow2(graph->node_count) - 1;
> +     sz += val;

Aren't here source nodes counted twice?  I'm trying now to wrap my head
around how this all is structured and laid out in memory (thus the
slowdown in review) so I am most probably missing something here.

> +     /* Fence */
> +     sz += sizeof(RTE_GRAPH_FENCE);
> +     sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
> +     graph->nodes_start = sz;
> +     /* For 0..N node objects with fence */
> +     STAILQ_FOREACH(graph_node, &graph->node_list, next) {
> +             sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
> +             sz += sizeof(struct rte_node);
> +             /* Pointer to next nodes(edges) */
> +             sz += sizeof(struct rte_node *) * graph_node->node->nb_edges;
> +     }
> +
> +     graph->mem_sz = sz;
> +     return sz;
> +}
> +
> +static void
> +graph_header_popluate(struct graph *_graph)
> +{
> +     struct rte_graph *graph = _graph->graph;
> +
> +     graph->tail = 0;
> +     graph->head = (int32_t)-_graph->src_node_count;
> +     graph->cir_mask = _graph->cir_mask;
> +     graph->nb_nodes = _graph->node_count;
> +     graph->cir_start = RTE_PTR_ADD(graph, _graph->cir_start);
> +     graph->nodes_start = _graph->nodes_start;
> +     graph->socket = _graph->socket;
> +     graph->id = _graph->id;
> +     memcpy(graph->name, _graph->name, RTE_GRAPH_NAMESIZE);

As I've mentioned above I'm learning the structure of the lib/memory so
quick question here.  My understanding is that rte_graph is a "view of
the 'struct graph' sufficient for worker" so does it need both id &
name?  Both of them seems to be used in error or dump/debug paths.  It
probably doesn't matter (e.g. for performance) - just asking because
'id' seems to be used only in one place (where name could replace it
probably).

> +     graph->fence = RTE_GRAPH_FENCE;
> +}
> +
> +static void
> +graph_nodes_populate(struct graph *_graph)
> +{
> +     rte_graph_off_t off = _graph->nodes_start;
> +     struct rte_graph *graph = _graph->graph;
> +     struct graph_node *graph_node;
> +     rte_edge_t count, nb_edges;
> +     const char *parent;
> +     rte_node_t pid;
> +
> +     STAILQ_FOREACH(graph_node, &_graph->node_list, next) {
> +             struct rte_node *node = RTE_PTR_ADD(graph, off);
> +             memset(node, 0, sizeof(*node));
> +             node->fence = RTE_GRAPH_FENCE;
> +             node->off = off;
> +             node->process = graph_node->node->process;
> +             memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
> +             pid = graph_node->node->parent_id;
> +             if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
> +                     parent = rte_node_id_to_name(pid);
> +                     memcpy(node->parent, parent, RTE_GRAPH_NAMESIZE);
> +             }
> +             node->id = graph_node->node->id;
> +             node->parent_id = pid;
> +             nb_edges = graph_node->node->nb_edges;
> +             node->nb_edges = nb_edges;
> +             off += sizeof(struct rte_node);
> +             /* Copy the name in first pass to replace with rte_node* later*/
> +             for (count = 0; count < nb_edges; count++)
> +                     node->nodes[count] = (struct rte_node *)&graph_node
> +                                                  ->adjacency_list[count]
> +                                                  ->node->name[0];

I'm not sure I understand what is going here.  Please see below ...

> +
> +             off += sizeof(struct rte_node *) * nb_edges;
> +             off = RTE_ALIGN(off, RTE_CACHE_LINE_SIZE);
> +             node->next = off;
> +             __rte_node_stream_alloc(graph, node);
> +     }
> +}
[...]
> +static int
> +graph_node_nexts_populate(struct graph *_graph)
> +{
> +     rte_node_t count, val;
> +     rte_graph_off_t off;
> +     struct rte_node *node;
> +     const struct rte_graph *graph = _graph->graph;
> +     const char *name;
> +
> +     rte_graph_foreach_node(count, off, graph, node) {
> +             for (val = 0; val < node->nb_edges; val++) {
> +                     name = (const char *)node->nodes[val];
> +                     node->nodes[val] = graph_node_name_to_ptr(graph, name);

... Is it so that during node the first loop above some node might refer
(by name) to other node that is not yet "registered" so instead of
storing rte_node pointer you stored actually pointer to name which you
now update to proper rte_node?

> +                     if (node->nodes[val] == NULL)
> +                             SET_ERR_JMP(EINVAL, fail, "%s not found", name);
> +             }
> +     }
> +
> +     return 0;
> +fail:
> +     return -rte_errno;
> +}
[...]

With regards
Andrzej Ostruszka

Reply via email to