1 /*
2 * Copyright © 2013-2016 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 /** \file
7 * \brief Macros to help interaction between hwloc and Intel Xeon Phi (MIC).
8 *
9 * Applications that use both hwloc and Intel Xeon Phi (MIC) may want to
10 * include this file so as to get topology information for MIC devices.
11 */
12
13 #ifndef HWLOC_INTEL_MIC_H
14 #define HWLOC_INTEL_MIC_H
15
16 #include <hwloc.h>
17 #include <hwloc/autogen/config.h>
18 #include <hwloc/helper.h>
19 #ifdef HWLOC_LINUX_SYS
20 #include <hwloc/linux.h>
21 #include <dirent.h>
22 #include <string.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33
34 /** \defgroup hwlocality_intel_mic Interoperability with Intel Xeon Phi (MIC)
35 *
36 * This interface offers ways to retrieve topology information about
37 * Intel Xeon Phi (MIC) devices.
38 *
39 * @{
40 */
41
42 /** \brief Get the CPU set of logical processors that are physically
43 * close to MIC device whose index is \p idx.
44 *
45 * Return the CPU set describing the locality of the MIC device whose index is \p idx.
46 *
47 * Topology \p topology and device index \p idx must match the local machine.
48 * I/O devices detection is not needed in the topology.
49 *
50 * The function only returns the locality of the device.
51 * If more information about the device is needed, OS objects should
52 * be used instead, see hwloc_intel_mic_get_device_osdev_by_index().
53 *
54 * This function is currently only implemented in a meaningful way for
55 * Linux; other systems will simply get a full cpuset.
56 */
57 static __hwloc_inline int
58 hwloc_intel_mic_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
59 int idx __hwloc_attribute_unused,
60 hwloc_cpuset_t set)
61 {
62 #ifdef HWLOC_LINUX_SYS
63 /* If we're on Linux, use the sysfs mechanism to get the local cpus */
64 #define HWLOC_INTEL_MIC_DEVICE_SYSFS_PATH_MAX 128
65 char path[HWLOC_INTEL_MIC_DEVICE_SYSFS_PATH_MAX];
66 DIR *sysdir = NULL;
67 struct dirent *dirent;
68 unsigned pcibus, pcidev, pcifunc;
69
70 if (!hwloc_topology_is_thissystem(topology)) {
71 errno = EINVAL;
72 return -1;
73 }
74
75 sprintf(path, "/sys/class/mic/mic%d", idx);
76 sysdir = opendir(path);
77 if (!sysdir)
78 return -1;
79
80 while ((dirent = readdir(sysdir)) != NULL) {
81 if (sscanf(dirent->d_name, "pci_%02x:%02x.%02x", &pcibus, &pcidev, &pcifunc) == 3) {
82 sprintf(path, "/sys/class/mic/mic%d/pci_%02x:%02x.%02x/local_cpus", idx, pcibus, pcidev, pcifunc);
83 if (hwloc_linux_read_path_as_cpumask(path, set) < 0
84 || hwloc_bitmap_iszero(set))
85 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
86 break;
87 }
88 }
89
90 closedir(sysdir);
91 #else
92 /* Non-Linux systems simply get a full cpuset */
93 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
94 #endif
95 return 0;
96 }
97
98 /** \brief Get the hwloc OS device object corresponding to the
99 * MIC device for the given index.
100 *
101 * Return the OS device object describing the MIC device whose index is \p idx.
102 * Return NULL if there is none.
103 *
104 * The topology \p topology does not necessarily have to match the current
105 * machine. For instance the topology may be an XML import of a remote host.
106 * I/O devices detection must be enabled in the topology.
107 *
108 * \note The corresponding PCI device object can be obtained by looking
109 * at the OS device parent object.
110 */
111 static __hwloc_inline hwloc_obj_t
112 hwloc_intel_mic_get_device_osdev_by_index(hwloc_topology_t topology,
113 unsigned idx)
114 {
115 hwloc_obj_t osdev = NULL;
116 while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
117 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
118 && osdev->name
119 && !strncmp("mic", osdev->name, 3)
120 && atoi(osdev->name + 3) == (int) idx)
121 return osdev;
122 }
123 return NULL;
124 }
125
126 /** @} */
127
128
129 #ifdef __cplusplus
130 } /* extern "C" */
131 #endif
132
133
134 #endif /* HWLOC_INTEL_MIC_H */