1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "env_internal.h" 7 8 #include <rte_config.h> 9 #include <rte_lcore.h> 10 11 #include "spdk/cpuset.h" 12 #include "spdk/log.h" 13 #include "spdk/string.h" 14 15 #define THREAD_SIBLINGS_FILE \ 16 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings" 17 18 uint32_t 19 spdk_env_get_core_count(void) 20 { 21 return rte_lcore_count(); 22 } 23 24 uint32_t 25 spdk_env_get_current_core(void) 26 { 27 return rte_lcore_id(); 28 } 29 30 uint32_t 31 spdk_env_get_main_core(void) 32 { 33 return rte_get_main_lcore(); 34 } 35 36 uint32_t 37 spdk_env_get_first_core(void) 38 { 39 return rte_get_next_lcore(-1, 0, 0); 40 } 41 42 uint32_t 43 spdk_env_get_last_core(void) 44 { 45 uint32_t i; 46 uint32_t last_core = UINT32_MAX; 47 48 SPDK_ENV_FOREACH_CORE(i) { 49 last_core = i; 50 } 51 52 assert(last_core != UINT32_MAX); 53 54 return last_core; 55 } 56 57 uint32_t 58 spdk_env_get_next_core(uint32_t prev_core) 59 { 60 unsigned lcore; 61 62 lcore = rte_get_next_lcore(prev_core, 0, 0); 63 if (lcore == RTE_MAX_LCORE) { 64 return UINT32_MAX; 65 } 66 return lcore; 67 } 68 69 int32_t 70 spdk_env_get_numa_id(uint32_t core) 71 { 72 if (core >= RTE_MAX_LCORE) { 73 return SPDK_ENV_NUMA_ID_ANY; 74 } 75 76 return rte_lcore_to_socket_id(core); 77 } 78 79 SPDK_LOG_DEPRECATION_REGISTER(env_socket_id, "spdk_env_get_socket_id", "v25.05", 0); 80 81 uint32_t 82 spdk_env_get_socket_id(uint32_t core) 83 { 84 SPDK_LOG_DEPRECATED(env_socket_id); 85 return spdk_env_get_numa_id(core); 86 } 87 88 void 89 spdk_env_get_cpuset(struct spdk_cpuset *cpuset) 90 { 91 uint32_t i; 92 93 spdk_cpuset_zero(cpuset); 94 SPDK_ENV_FOREACH_CORE(i) { 95 spdk_cpuset_set_cpu(cpuset, i, true); 96 } 97 } 98 99 static bool 100 env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core) 101 { 102 #ifdef __linux__ 103 struct spdk_cpuset smt_siblings; 104 char path[PATH_MAX]; 105 FILE *f; 106 char *line = NULL; 107 size_t len = 0; 108 ssize_t read; 109 bool valid = false; 110 111 snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core); 112 f = fopen(path, "r"); 113 if (f == NULL) { 114 SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno)); 115 return false; 116 } 117 read = getline(&line, &len, f); 118 if (read == -1) { 119 SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno)); 120 goto ret; 121 } 122 123 /* Remove trailing newline */ 124 line[strlen(line) - 1] = 0; 125 if (spdk_cpuset_parse(&smt_siblings, line)) { 126 SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path); 127 goto ret; 128 } 129 130 valid = true; 131 spdk_cpuset_or(cpuset, &smt_siblings); 132 ret: 133 free(line); 134 fclose(f); 135 return valid; 136 #else 137 return false; 138 #endif 139 } 140 141 bool 142 spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core) 143 { 144 uint32_t i; 145 146 spdk_cpuset_zero(cpuset); 147 148 if (core != UINT32_MAX) { 149 return env_core_get_smt_cpuset(cpuset, core); 150 } 151 152 SPDK_ENV_FOREACH_CORE(i) { 153 if (!env_core_get_smt_cpuset(cpuset, i)) { 154 return false; 155 } 156 } 157 158 return true; 159 } 160 161 int 162 spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg) 163 { 164 int rc; 165 166 rc = rte_eal_remote_launch(fn, arg, core); 167 168 return rc; 169 } 170 171 void 172 spdk_env_thread_wait_all(void) 173 { 174 rte_eal_mp_wait_lcore(); 175 } 176