Line data Source code
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 0 : spdk_env_get_core_count(void)
20 : {
21 0 : return rte_lcore_count();
22 : }
23 :
24 : uint32_t
25 0 : spdk_env_get_current_core(void)
26 : {
27 0 : return rte_lcore_id();
28 : }
29 :
30 : uint32_t
31 0 : spdk_env_get_main_core(void)
32 : {
33 0 : return rte_get_main_lcore();
34 : }
35 :
36 : uint32_t
37 0 : spdk_env_get_first_core(void)
38 : {
39 0 : return rte_get_next_lcore(-1, 0, 0);
40 : }
41 :
42 : uint32_t
43 0 : spdk_env_get_last_core(void)
44 : {
45 : uint32_t i;
46 0 : uint32_t last_core = UINT32_MAX;
47 :
48 0 : SPDK_ENV_FOREACH_CORE(i) {
49 0 : last_core = i;
50 : }
51 :
52 0 : assert(last_core != UINT32_MAX);
53 :
54 0 : return last_core;
55 : }
56 :
57 : uint32_t
58 0 : spdk_env_get_next_core(uint32_t prev_core)
59 : {
60 : unsigned lcore;
61 :
62 0 : lcore = rte_get_next_lcore(prev_core, 0, 0);
63 0 : if (lcore == RTE_MAX_LCORE) {
64 0 : return UINT32_MAX;
65 : }
66 0 : return lcore;
67 : }
68 :
69 : uint32_t
70 0 : spdk_env_get_socket_id(uint32_t core)
71 : {
72 0 : if (core >= RTE_MAX_LCORE) {
73 0 : return SPDK_ENV_SOCKET_ID_ANY;
74 : }
75 :
76 0 : return rte_lcore_to_socket_id(core);
77 : }
78 :
79 : void
80 0 : spdk_env_get_cpuset(struct spdk_cpuset *cpuset)
81 : {
82 : uint32_t i;
83 :
84 0 : spdk_cpuset_zero(cpuset);
85 0 : SPDK_ENV_FOREACH_CORE(i) {
86 0 : spdk_cpuset_set_cpu(cpuset, i, true);
87 : }
88 0 : }
89 :
90 : static bool
91 0 : env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
92 : {
93 : #ifdef __linux__
94 0 : struct spdk_cpuset smt_siblings;
95 0 : char path[PATH_MAX];
96 : FILE *f;
97 0 : char *line = NULL;
98 0 : size_t len = 0;
99 : ssize_t read;
100 0 : bool valid = false;
101 :
102 0 : snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core);
103 0 : f = fopen(path, "r");
104 0 : if (f == NULL) {
105 0 : SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno));
106 0 : return false;
107 : }
108 0 : read = getline(&line, &len, f);
109 0 : if (read == -1) {
110 0 : SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno));
111 0 : goto ret;
112 : }
113 :
114 : /* Remove trailing newline */
115 0 : line[strlen(line) - 1] = 0;
116 0 : if (spdk_cpuset_parse(&smt_siblings, line)) {
117 0 : SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path);
118 0 : goto ret;
119 : }
120 :
121 0 : valid = true;
122 0 : spdk_cpuset_or(cpuset, &smt_siblings);
123 0 : ret:
124 0 : free(line);
125 0 : fclose(f);
126 0 : return valid;
127 : #else
128 : return false;
129 : #endif
130 : }
131 :
132 : bool
133 0 : spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
134 : {
135 : uint32_t i;
136 :
137 0 : spdk_cpuset_zero(cpuset);
138 :
139 0 : if (core != UINT32_MAX) {
140 0 : return env_core_get_smt_cpuset(cpuset, core);
141 : }
142 :
143 0 : SPDK_ENV_FOREACH_CORE(i) {
144 0 : if (!env_core_get_smt_cpuset(cpuset, i)) {
145 0 : return false;
146 : }
147 : }
148 :
149 0 : return true;
150 : }
151 :
152 : int
153 0 : spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg)
154 : {
155 : int rc;
156 :
157 0 : rc = rte_eal_remote_launch(fn, arg, core);
158 :
159 0 : return rc;
160 : }
161 :
162 : void
163 0 : spdk_env_thread_wait_all(void)
164 : {
165 0 : rte_eal_mp_wait_lcore();
166 0 : }
|