Linux Perf
topology.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include "tests.h"
6 #include "util.h"
7 #include "session.h"
8 #include "evlist.h"
9 #include "debug.h"
10 
11 #define TEMPL "/tmp/perf-test-XXXXXX"
12 #define DATA_SIZE 10
13 
14 static int get_temp(char *path)
15 {
16  int fd;
17 
18  strcpy(path, TEMPL);
19 
20  fd = mkstemp(path);
21  if (fd < 0) {
22  perror("mkstemp failed");
23  return -1;
24  }
25 
26  close(fd);
27  return 0;
28 }
29 
30 static int session_write_header(char *path)
31 {
32  struct perf_session *session;
33  struct perf_data data = {
34  .file = {
35  .path = path,
36  },
37  .mode = PERF_DATA_MODE_WRITE,
38  };
39 
40  session = perf_session__new(&data, false, NULL);
41  TEST_ASSERT_VAL("can't get session", session);
42 
43  session->evlist = perf_evlist__new_default();
44  TEST_ASSERT_VAL("can't get evlist", session->evlist);
45 
48 
49  session->header.data_size += DATA_SIZE;
50 
51  TEST_ASSERT_VAL("failed to write header",
52  !perf_session__write_header(session, session->evlist, data.file.fd, true));
53 
54  perf_session__delete(session);
55 
56  return 0;
57 }
58 
59 static int check_cpu_topology(char *path, struct cpu_map *map)
60 {
61  struct perf_session *session;
62  struct perf_data data = {
63  .file = {
64  .path = path,
65  },
66  .mode = PERF_DATA_MODE_READ,
67  };
68  int i;
69 
70  session = perf_session__new(&data, false, NULL);
71  TEST_ASSERT_VAL("can't get session", session);
72 
73  /* On platforms with large numbers of CPUs process_cpu_topology()
74  * might issue an error while reading the perf.data file section
75  * HEADER_CPU_TOPOLOGY and the cpu_topology_map pointed to by member
76  * cpu is a NULL pointer.
77  * Example: On s390
78  * CPU 0 is on core_id 0 and physical_package_id 6
79  * CPU 1 is on core_id 1 and physical_package_id 3
80  *
81  * Core_id and physical_package_id are platform and architecture
82  * dependend and might have higher numbers than the CPU id.
83  * This actually depends on the configuration.
84  *
85  * In this case process_cpu_topology() prints error message:
86  * "socket_id number is too big. You may need to upgrade the
87  * perf tool."
88  *
89  * This is the reason why this test might be skipped.
90  */
91  if (!session->header.env.cpu)
92  return TEST_SKIP;
93 
94  for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
95  if (!cpu_map__has(map, i))
96  continue;
97  pr_debug("CPU %d, core %d, socket %d\n", i,
98  session->header.env.cpu[i].core_id,
99  session->header.env.cpu[i].socket_id);
100  }
101 
102  for (i = 0; i < map->nr; i++) {
103  TEST_ASSERT_VAL("Core ID doesn't match",
104  (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
105 
106  TEST_ASSERT_VAL("Socket ID doesn't match",
107  (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
108  }
109 
110  perf_session__delete(session);
111 
112  return 0;
113 }
114 
115 int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
116 {
117  char path[PATH_MAX];
118  struct cpu_map *map;
119  int ret = TEST_FAIL;
120 
121  TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
122 
123  pr_debug("templ file: %s\n", path);
124 
125  if (session_write_header(path))
126  goto free_path;
127 
128  map = cpu_map__new(NULL);
129  if (map == NULL) {
130  pr_debug("failed to get system cpumap\n");
131  goto free_path;
132  }
133 
134  ret = check_cpu_topology(path, map);
135  cpu_map__put(map);
136 
137 free_path:
138  unlink(path);
139  return ret;
140 }
int nr
Definition: cpumap.h:14
struct perf_evlist * evlist
Definition: session.h:25
int fd
Definition: data.h:14
struct perf_evlist * perf_evlist__new_default(void)
Definition: evlist.c:64
#define TEST_ASSERT_VAL(text, cond)
Definition: tests.h:7
struct perf_data_file file
Definition: data.h:18
struct perf_env env
Definition: header.h:82
Definition: cpumap.h:12
static int get_temp(char *path)
Definition: topology.c:14
void perf_session__delete(struct perf_session *session)
Definition: session.c:187
void cpu_map__put(struct cpu_map *map)
Definition: cpumap.c:298
int nr_cpus_avail
Definition: env.h:42
#define pr_debug(fmt,...)
Definition: json.h:27
static struct perf_session * session
Definition: builtin-lock.c:34
struct cpu_topology_map * cpu
Definition: env.h:60
#define PATH_MAX
Definition: jevents.c:1042
void perf_header__set_feat(struct perf_header *header, int feat)
Definition: header.c:76
bool cpu_map__has(struct cpu_map *cpus, int cpu)
Definition: cpumap.c:616
Definition: data.h:17
static int check_cpu_topology(char *path, struct cpu_map *map)
Definition: topology.c:59
int socket_id
Definition: env.h:9
int map[]
Definition: cpumap.h:15
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
Definition: session.c:116
Definition: jevents.c:228
int core_id
Definition: env.h:10
Definition: tests.h:30
#define TEMPL
Definition: topology.c:11
struct perf_header header
Definition: session.h:23
int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
Definition: cpumap.c:375
static int session_write_header(char *path)
Definition: topology.c:30
int perf_session__write_header(struct perf_session *session, struct perf_evlist *evlist, int fd, bool at_exit)
Definition: header.c:2765
#define DATA_SIZE
Definition: topology.c:12
struct cpu_map * cpu_map__new(const char *cpu_list)
Definition: cpumap.c:125
int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
Definition: cpumap.c:320
const char * path
Definition: data.h:13
int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: topology.c:115
u64 data_size
Definition: header.h:79