1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
13 #include <rte_memory.h>
14 #include <rte_launch.h>
16 #include <rte_eal_memconfig.h>
17 #include <rte_per_lcore.h>
18 #include <rte_lcore.h>
19 #include <rte_atomic.h>
20 #include <rte_branch_prediction.h>
22 #include <rte_string_fns.h>
23 #include <rte_debug.h>
25 #include "eal_private.h"
27 TAILQ_HEAD(rte_tailq_elem_head
, rte_tailq_elem
);
28 /* local tailq list */
29 static struct rte_tailq_elem_head rte_tailq_elem_head
=
30 TAILQ_HEAD_INITIALIZER(rte_tailq_elem_head
);
32 /* number of tailqs registered, -1 before call to rte_eal_tailqs_init */
33 static int rte_tailqs_count
= -1;
35 struct rte_tailq_head
*
36 rte_eal_tailq_lookup(const char *name
)
39 struct rte_mem_config
*mcfg
= rte_eal_get_configuration()->mem_config
;
44 for (i
= 0; i
< RTE_MAX_TAILQ
; i
++) {
45 if (!strncmp(name
, mcfg
->tailq_head
[i
].name
,
46 RTE_TAILQ_NAMESIZE
-1))
47 return &mcfg
->tailq_head
[i
];
54 rte_dump_tailq(FILE *f
)
56 struct rte_mem_config
*mcfg
;
59 mcfg
= rte_eal_get_configuration()->mem_config
;
61 rte_rwlock_read_lock(&mcfg
->qlock
);
62 for (i
= 0; i
< RTE_MAX_TAILQ
; i
++) {
63 const struct rte_tailq_head
*tailq
= &mcfg
->tailq_head
[i
];
64 const struct rte_tailq_entry_head
*head
= &tailq
->tailq_head
;
66 fprintf(f
, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n",
67 i
, tailq
->name
, head
->tqh_first
, head
->tqh_last
);
69 rte_rwlock_read_unlock(&mcfg
->qlock
);
72 static struct rte_tailq_head
*
73 rte_eal_tailq_create(const char *name
)
75 struct rte_tailq_head
*head
= NULL
;
77 if (!rte_eal_tailq_lookup(name
) &&
78 (rte_tailqs_count
+ 1 < RTE_MAX_TAILQ
)) {
79 struct rte_mem_config
*mcfg
;
81 mcfg
= rte_eal_get_configuration()->mem_config
;
82 head
= &mcfg
->tailq_head
[rte_tailqs_count
];
83 snprintf(head
->name
, sizeof(head
->name
) - 1, "%s", name
);
84 TAILQ_INIT(&head
->tailq_head
);
91 /* local register, used to store "early" tailqs before rte_eal_init() and to
92 * ensure secondary process only registers tailqs once. */
94 rte_eal_tailq_local_register(struct rte_tailq_elem
*t
)
96 struct rte_tailq_elem
*temp
;
98 TAILQ_FOREACH(temp
, &rte_tailq_elem_head
, next
) {
99 if (!strncmp(t
->name
, temp
->name
, sizeof(temp
->name
)))
103 TAILQ_INSERT_TAIL(&rte_tailq_elem_head
, t
, next
);
108 rte_eal_tailq_update(struct rte_tailq_elem
*t
)
110 if (rte_eal_process_type() == RTE_PROC_PRIMARY
) {
111 /* primary process is the only one that creates */
112 t
->head
= rte_eal_tailq_create(t
->name
);
114 t
->head
= rte_eal_tailq_lookup(t
->name
);
119 rte_eal_tailq_register(struct rte_tailq_elem
*t
)
121 if (rte_eal_tailq_local_register(t
) < 0) {
123 "%s tailq is already registered\n", t
->name
);
127 /* if a register happens after rte_eal_tailqs_init(), then we can update
129 if (rte_tailqs_count
>= 0) {
130 rte_eal_tailq_update(t
);
131 if (t
->head
== NULL
) {
133 "Cannot initialize tailq: %s\n", t
->name
);
134 TAILQ_REMOVE(&rte_tailq_elem_head
, t
, next
);
147 rte_eal_tailqs_init(void)
149 struct rte_tailq_elem
*t
;
151 rte_tailqs_count
= 0;
153 TAILQ_FOREACH(t
, &rte_tailq_elem_head
, next
) {
154 /* second part of register job for "early" tailqs, see
155 * rte_eal_tailq_register and EAL_REGISTER_TAILQ */
156 rte_eal_tailq_update(t
);
157 if (t
->head
== NULL
) {
159 "Cannot initialize tailq: %s\n", t
->name
);
160 /* TAILQ_REMOVE not needed, error is already fatal */
168 rte_dump_tailq(stderr
);