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