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 uint32_t 70 spdk_env_get_socket_id(uint32_t core) 71 { 72 if (core >= RTE_MAX_LCORE) { 73 return SPDK_ENV_SOCKET_ID_ANY; 74 } 75 76 return rte_lcore_to_socket_id(core); 77 } 78 79 void 80 spdk_env_get_cpuset(struct spdk_cpuset *cpuset) 81 { 82 uint32_t i; 83 84 spdk_cpuset_zero(cpuset); 85 SPDK_ENV_FOREACH_CORE(i) { 86 spdk_cpuset_set_cpu(cpuset, i, true); 87 } 88 } 89 90 static bool 91 env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core) 92 { 93 #ifdef __linux__ 94 struct spdk_cpuset smt_siblings; 95 char path[PATH_MAX]; 96 FILE *f; 97 char *line = NULL; 98 size_t len = 0; 99 ssize_t read; 100 bool valid = false; 101 102 snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core); 103 f = fopen(path, "r"); 104 if (f == NULL) { 105 SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno)); 106 return false; 107 } 108 read = getline(&line, &len, f); 109 if (read == -1) { 110 SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno)); 111 goto ret; 112 } 113 114 /* Remove trailing newline */ 115 line[strlen(line) - 1] = 0; 116 if (spdk_cpuset_parse(&smt_siblings, line)) { 117 SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path); 118 goto ret; 119 } 120 121 valid = true; 122 spdk_cpuset_or(cpuset, &smt_siblings); 123 ret: 124 free(line); 125 fclose(f); 126 return valid; 127 #else 128 return false; 129 #endif 130 } 131 132 bool 133 spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core) 134 { 135 uint32_t i; 136 137 spdk_cpuset_zero(cpuset); 138 139 if (core != UINT32_MAX) { 140 return env_core_get_smt_cpuset(cpuset, core); 141 } 142 143 SPDK_ENV_FOREACH_CORE(i) { 144 if (!env_core_get_smt_cpuset(cpuset, i)) { 145 return false; 146 } 147 } 148 149 return true; 150 } 151 152 int 153 spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg) 154 { 155 int rc; 156 157 rc = rte_eal_remote_launch(fn, arg, core); 158 159 return rc; 160 } 161 162 void 163 spdk_env_thread_wait_all(void) 164 { 165 rte_eal_mp_wait_lcore(); 166 } 167