1 /*
2 * Copyright (C) 2018 Joseph Benden <joe@benden.us>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
11 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
12 * NON-INFRINGEMENT. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 *
19 * In addition, as a special exception, the copyright holders give
20 * permission to link the code of portions of this program with the
21 * OpenSSL library under certain conditions as described in each
22 * individual source file, and distribute linked combinations
23 * including the two.
24 * You must obey the GNU General Public License in all respects
25 * for all of the code used other than OpenSSL. If you modify
26 * file(s) with this exception, you may extend this exception to your
27 * version of the file(s), but you are not obligated to do so. If you
28 * do not wish to do so, delete this exception statement from your
29 * version. If you delete this exception statement from all source
30 * files in the program, then also delete it here.
31 */
32
33 #include <hwloc.h>
34 #include <assert.h>
35 #include <limits.h>
36 #include <sys/types.h>
37
38 #include "aircrack-util/cpuset.h"
39
40 struct ac_cpuset
41 {
42 size_t nbThreads;
43
44 hwloc_topology_t topology;
45 hwloc_cpuset_t * hwloc_cpusets;
46 };
47
ac_cpuset_new(void)48 ac_cpuset_t * ac_cpuset_new(void) { return malloc(sizeof(struct ac_cpuset)); }
49
ac_cpuset_free(ac_cpuset_t * cpuset)50 void ac_cpuset_free(ac_cpuset_t * cpuset) { free(cpuset); }
51
ac_cpuset_init(ac_cpuset_t * cpuset)52 void ac_cpuset_init(ac_cpuset_t * cpuset)
53 {
54 assert(cpuset != NULL);
55
56 cpuset->nbThreads = 0;
57 cpuset->hwloc_cpusets = NULL;
58
59 hwloc_topology_init(&cpuset->topology);
60 hwloc_topology_load(cpuset->topology);
61 }
62
ac_cpuset_destroy(ac_cpuset_t * cpuset)63 void ac_cpuset_destroy(ac_cpuset_t * cpuset)
64 {
65 assert(cpuset != NULL);
66
67 if (cpuset->hwloc_cpusets != NULL)
68 {
69 free(cpuset->hwloc_cpusets);
70 cpuset->hwloc_cpusets = NULL;
71 }
72
73 hwloc_topology_destroy(cpuset->topology);
74 }
75
ac_cpuset_distribute(ac_cpuset_t * cpuset,size_t count)76 void ac_cpuset_distribute(ac_cpuset_t * cpuset, size_t count)
77 {
78 assert(cpuset != NULL);
79
80 cpuset->nbThreads = count;
81 cpuset->hwloc_cpusets = calloc(count, sizeof(hwloc_cpuset_t));
82
83 if (!cpuset->hwloc_cpusets) return;
84
85 hwloc_obj_t root = hwloc_get_root_obj(cpuset->topology);
86
87 #if defined(HWLOC_API_VERSION) && HWLOC_API_VERSION > 0x00010800
88 hwloc_distrib(cpuset->topology,
89 &root,
90 1u,
91 cpuset->hwloc_cpusets,
92 (unsigned int) count,
93 INT_MAX,
94 0u);
95 #else
96 hwloc_distributev(cpuset->topology,
97 &root,
98 1u,
99 cpuset->hwloc_cpusets,
100 (unsigned int) count,
101 INT_MAX);
102 #endif
103 }
104
ac_cpuset_bind_thread_at(ac_cpuset_t * cpuset,pthread_t tid,size_t idx)105 void ac_cpuset_bind_thread_at(ac_cpuset_t * cpuset, pthread_t tid, size_t idx)
106 {
107 assert(cpuset != NULL);
108
109 if (idx > cpuset->nbThreads) return;
110
111 hwloc_bitmap_singlify(cpuset->hwloc_cpusets[idx]);
112
113 if (hwloc_set_thread_cpubind(cpuset->topology,
114 tid,
115 cpuset->hwloc_cpusets[idx],
116 HWLOC_CPUBIND_THREAD))
117 {
118 char * str;
119 int error = errno;
120 hwloc_bitmap_asprintf(&str, cpuset->hwloc_cpusets[idx]);
121 fprintf(stderr,
122 "Couldn't bind thread to cpuset %s: %s\n",
123 str,
124 strerror(error));
125 free(str);
126 }
127 }
128