Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <string.h>
8 : :
9 : : #include <rte_eal.h>
10 : : #include <rte_eal_memconfig.h>
11 : : #include <rte_errno.h>
12 : : #include <rte_log.h>
13 : : #include <rte_string_fns.h>
14 : :
15 : : #include <eal_export.h>
16 : : #include "eal_private.h"
17 : : #include "eal_memcfg.h"
18 : :
19 : : TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem);
20 : : /* local tailq list */
21 : : static struct rte_tailq_elem_head rte_tailq_elem_head =
22 : : TAILQ_HEAD_INITIALIZER(rte_tailq_elem_head);
23 : :
24 : : /* number of tailqs registered, -1 before call to rte_eal_tailqs_init */
25 : : static int rte_tailqs_count = -1;
26 : :
27 : : RTE_EXPORT_SYMBOL(rte_eal_tailq_lookup)
28 : : struct rte_tailq_head *
29 : 5920 : rte_eal_tailq_lookup(const char *name)
30 : : {
31 : : unsigned i;
32 : 5920 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
33 : :
34 [ - + ]: 5920 : if (name == NULL) {
35 : 0 : rte_errno = EINVAL;
36 : 0 : return NULL;
37 : : }
38 : :
39 [ + + ]: 182275 : for (i = 0; i < RTE_MAX_TAILQ; i++) {
40 [ + + ]: 177082 : if (!strncmp(name, mcfg->tailq_head[i].name,
41 : : RTE_TAILQ_NAMESIZE-1))
42 : 727 : return &mcfg->tailq_head[i];
43 : : }
44 : :
45 : 5193 : rte_errno = ENOENT;
46 : 5193 : return NULL;
47 : : }
48 : :
49 : : RTE_EXPORT_SYMBOL(rte_dump_tailq)
50 : : void
51 : 0 : rte_dump_tailq(FILE *f)
52 : : {
53 : : struct rte_mem_config *mcfg;
54 : : unsigned i = 0;
55 : :
56 : 0 : mcfg = rte_eal_get_configuration()->mem_config;
57 : :
58 : 0 : rte_mcfg_tailq_read_lock();
59 [ # # ]: 0 : for (i = 0; i < RTE_MAX_TAILQ; i++) {
60 : : const struct rte_tailq_head *tailq = &mcfg->tailq_head[i];
61 : : const struct rte_tailq_entry_head *head = &tailq->tailq_head;
62 : :
63 : : fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n",
64 : 0 : i, tailq->name, head->tqh_first, head->tqh_last);
65 : : }
66 : 0 : rte_mcfg_tailq_read_unlock();
67 : 0 : }
68 : :
69 : : static struct rte_tailq_head *
70 : 5192 : rte_eal_tailq_create(const char *name)
71 : : {
72 : : struct rte_tailq_head *head = NULL;
73 : :
74 [ - + ]: 5192 : if (strlen(name) >= sizeof(head->name)) {
75 : 0 : EAL_LOG(ERR, "tailq name '%s' is too long", name);
76 : 0 : rte_errno = ENAMETOOLONG;
77 : 0 : return NULL;
78 : : }
79 : :
80 [ + - ]: 5192 : if (!rte_eal_tailq_lookup(name) &&
81 [ + - ]: 5192 : (rte_tailqs_count + 1 < RTE_MAX_TAILQ)) {
82 : : struct rte_mem_config *mcfg;
83 : :
84 : 5192 : mcfg = rte_eal_get_configuration()->mem_config;
85 : 5192 : head = &mcfg->tailq_head[rte_tailqs_count];
86 : 5192 : strlcpy(head->name, name, sizeof(head->name) - 1);
87 : 5192 : TAILQ_INIT(&head->tailq_head);
88 : 5192 : rte_tailqs_count++;
89 : : }
90 : :
91 : : return head;
92 : : }
93 : :
94 : : /* local register, used to store "early" tailqs before rte_eal_init() and to
95 : : * ensure secondary process only registers tailqs once. */
96 : : static int
97 : 8006 : rte_eal_tailq_local_register(struct rte_tailq_elem *t)
98 : : {
99 : : struct rte_tailq_elem *temp;
100 : :
101 [ + + ]: 120120 : TAILQ_FOREACH(temp, &rte_tailq_elem_head, next) {
102 [ + + ]: 112115 : if (!strncmp(t->name, temp->name, sizeof(temp->name)))
103 : : return -1;
104 : : }
105 : :
106 : 8005 : TAILQ_INSERT_TAIL(&rte_tailq_elem_head, t, next);
107 : 8005 : return 0;
108 : : }
109 : :
110 : : static void
111 : 5917 : rte_eal_tailq_update(struct rte_tailq_elem *t)
112 : : {
113 [ + + ]: 5917 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
114 : : /* primary process is the only one that creates */
115 : 5192 : t->head = rte_eal_tailq_create(t->name);
116 : : } else {
117 : 725 : t->head = rte_eal_tailq_lookup(t->name);
118 : : }
119 : 5917 : }
120 : :
121 : : RTE_EXPORT_SYMBOL(rte_eal_tailq_register)
122 : : int
123 : 8006 : rte_eal_tailq_register(struct rte_tailq_elem *t)
124 : : {
125 [ + + ]: 8006 : if (rte_eal_tailq_local_register(t) < 0) {
126 : 1 : EAL_LOG(ERR,
127 : : "%s tailq is already registered", t->name);
128 : 1 : rte_errno = EEXIST;
129 : 1 : goto error;
130 : : }
131 : :
132 : : /* if a register happens after rte_eal_tailqs_init(), then we can update
133 : : * tailq head */
134 [ + + ]: 8005 : if (rte_tailqs_count >= 0) {
135 : 1 : rte_eal_tailq_update(t);
136 [ - + ]: 1 : if (t->head == NULL) {
137 : 0 : EAL_LOG(ERR,
138 : : "Cannot initialize tailq: %s", t->name);
139 [ # # ]: 0 : TAILQ_REMOVE(&rte_tailq_elem_head, t, next);
140 : 0 : goto error;
141 : : }
142 : : }
143 : :
144 : : return 0;
145 : :
146 : 1 : error:
147 : 1 : t->head = NULL;
148 : 1 : return -1;
149 : : }
150 : :
151 : : int
152 : 204 : rte_eal_tailqs_init(void)
153 : : {
154 : : struct rte_tailq_elem *t;
155 : :
156 : 204 : rte_tailqs_count = 0;
157 : :
158 [ + + ]: 6120 : TAILQ_FOREACH(t, &rte_tailq_elem_head, next) {
159 : : /* second part of register job for "early" tailqs, see
160 : : * rte_eal_tailq_register and EAL_REGISTER_TAILQ */
161 : 5916 : rte_eal_tailq_update(t);
162 [ - + ]: 5916 : if (t->head == NULL) {
163 : 0 : EAL_LOG(ERR,
164 : : "Cannot initialize tailq: %s", t->name);
165 : : /* TAILQ_REMOVE not needed, error is already fatal */
166 : 0 : goto fail;
167 : : }
168 : : }
169 : :
170 : : return 0;
171 : :
172 : : fail:
173 : 0 : rte_dump_tailq(stderr);
174 : 0 : return -1;
175 : : }
|