Flowgrind
Advanced TCP traffic generator
fg_affinity.c
Go to the documentation of this file.
1 
6 /*
7  * Copyright (C) 2014 Alexander Zimmermann <alexander.zimmermann@netapp.com>
8  *
9  * This file is part of Flowgrind.
10  *
11  * Flowgrind is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * Flowgrind is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Flowgrind. If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif /* HAVE_CONFIG_H */
29 
30 #ifdef HAVE_PTHREAD_NP_H
31 #include <pthread_np.h>
32 #endif /* HAVE_PTHREAD_NP */
33 
34 #ifdef HAVE_SYS_CPUSET_H
35 #include <sys/param.h>
36 #include <sys/cpuset.h>
37 #endif /* HAVE_SYS_CPUSET */
38 
39 /* OS X hasn't defined pthread_[set|get]affinity_np */
40 #if !defined(HAVE_PTHREAD_AFFINITY_NP) && defined HAVE_THREAD_POLICY
41 #include <mach/mach.h>
42 #include <mach/thread_policy.h>
43 #endif /* !defined(HAVE_PTHREAD_AFFINITY_NP) && defined HAVE_THREAD_POLICY */
44 
45 #include <stdbool.h>
46 #include <errno.h>
47 #include <unistd.h>
48 
49 #include "fg_affinity.h"
50 
51 #if (!(HAVE_CPU_SET_T) && HAVE_CPUSET_T)
52 
53 typedef cpuset_t cpu_set_t;
54 #endif /* HAVE_CPUSET_T */
55 
56 int get_ncores(enum ncore_query query)
57 {
58  switch (query) {
59  case NCORE_CONFIG:
60  /* processors configured */
61  return (int)sysconf(_SC_NPROCESSORS_CONF);
62  break;
63  case NCORE_CURRENT:
64  /* processors available */
65  return (int)sysconf(_SC_NPROCESSORS_ONLN);
66  break;
67  default:
68  errno = EINVAL;
69  return -1;
70  }
71 }
72 
73 /* Linux and FreeBSD have pthread_[set|get]affinity_np */
74 #if defined HAVE_PTHREAD_AFFINITY_NP
75 int pthread_setaffinity(pthread_t thread, unsigned core)
76 {
77  cpu_set_t cpuset;
78  CPU_ZERO(&cpuset);
79  CPU_SET(core, &cpuset);
80 
81  int rc = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
82  return (rc == 0 ? 0 : -1);
83 }
84 
85 int pthread_getaffinity(pthread_t thread, unsigned *core)
86 {
87  cpu_set_t cpuset;
88  int rc = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
89  if (rc)
90  return -1;
91 
92  /* If the cpuset contains only one CPU, then that's the answer. For
93  * all other cpuset contents, we treat the binding as unknown */
94  core = NULL;
95  bool core_found = false;
96  for (unsigned i = 0; i < CPU_SETSIZE; i++) {
97  if (CPU_ISSET(i, &cpuset)) {
98  if (!core_found) {
99  core_found = true;
100  *core = i;
101  } else {
102  core_found = false;
103  core = NULL;
104  break;
105  }
106  }
107  }
108 
109  return (core_found ? 0 : -1);
110 }
111 /* OS X hasn't defined pthread_[set|get]affinity_np */
112 #elif defined HAVE_THREAD_POLICY
113 int pthread_setaffinity(pthread_t thread, unsigned core)
114 {
115  /* Convert pthread ID */
116  mach_port_t mach_thread = pthread_mach_thread_np(thread);
117  /* core + 1 to avoid using THREAD_AFFINITY_TAG_NULL */
118  thread_affinity_policy_data_t policy = { core + 1 };
119 
120  kern_return_t rc = thread_policy_set(mach_thread,
121  THREAD_AFFINITY_POLICY,
122  (thread_policy_t) &policy,
123  THREAD_AFFINITY_POLICY_COUNT);
124 
125  return (rc == KERN_SUCCESS ? 0 : -1);
126 }
127 
128 int pthread_getaffinity(pthread_t thread, unsigned *core)
129 {
130  /* Convert pthread ID */
131  mach_port_t mach_thread = pthread_mach_thread_np(thread);
132  thread_affinity_policy_data_t policy;
133  mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
134  boolean_t get_default = FALSE;
135 
136  kern_return_t rc = thread_policy_get(mach_thread,
137  THREAD_AFFINITY_POLICY,
138  (thread_policy_t) &policy, &count,
139  &get_default);
140  *core = (unsigned)policy.affinity_tag;
141 
142  return (rc == KERN_SUCCESS ? 0 : -1);
143 }
144 #endif /* HAVE_PTHREAD_AFFINITY_NP */
ncore_query
ncore_query
Query type for get_ncores().
Definition: fg_affinity.h:36
fg_affinity.h
CPU affinity routines used by Flowgrind.
NCORE_CONFIG
@ NCORE_CONFIG
Total number of processors configured.
Definition: fg_affinity.h:38
NCORE_CURRENT
@ NCORE_CURRENT
Processors available to the current process.
Definition: fg_affinity.h:40
get_ncores
int get_ncores(enum ncore_query query)
Return either the total number of configured or available cores.
Definition: fg_affinity.c:56
pthread_getaffinity
int pthread_getaffinity(pthread_t thread, unsigned *core)
Returns the CPU affinity of thread thread in the buffer pointed to by core.
Definition: fg_affinity.c:85
core
static int core
CPU core to which flowgrindd should bind to.
Definition: flowgrindd.c:101
config.h
pthread_setaffinity
int pthread_setaffinity(pthread_t thread, unsigned core)
Set CPU affinity of the thread thread to the core core.
Definition: fg_affinity.c:75