-
Notifications
You must be signed in to change notification settings - Fork 0
/
03-thread.cc
105 lines (87 loc) · 2.48 KB
/
03-thread.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//
// Program
// This program creates thread(s) and manipulate their CPU affinity.
//
// Compile
// g++ -Wall -Wextra -pedantic -std=c++17 -pthread -o 03-thread 03-thread.cc
//
// Execution
// ./03-thread
//
#include <iostream>
#include <iomanip>
#include <thread>
#include <mutex>
#include <vector>
#include <sched.h>
using namespace std::chrono;
//
// Handy function to get CPU id where a specific
// process id is running.
//
int get_cpu_id(pthread_t p_id, unsigned int cpu_count) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
// Get cpu affinity
// sched_getaffinity can also be used
int ret = pthread_getaffinity_np(p_id, sizeof(cpu_set_t), &cpu_set);
if (ret != 0) {
std::cout << "Error: pthread_getaffinity_np error code # " << errno << '\n';
return -1;
}
// Find out which cpu id is set
for (auto c = 0U; c < cpu_count; ++c) {
if (CPU_ISSET(c, &cpu_set)) {
return c;
}
}
return -1;
}
//
// Handy function to set CPU id for a specific process.
//
void set_cpu_id(pthread_t p_id, unsigned int cpu_id) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(cpu_id, &cpu_set);
// Set CPU affinity
// sched_setaffinity can also be used
int ret = pthread_setaffinity_np(p_id, sizeof(cpu_set_t), &cpu_set);
if (ret != 0) {
std::cout << "Error: pthread_setaffinity_np error code # " << errno << '\n';
}
}
//
// Entry function
//
int main() {
// Create & start thread
std::cout << "--- Thread and manipulate affinity ---" << '\n';
unsigned int cpus = std::thread::hardware_concurrency();
std::cout << "Number of CPUs: " << cpus << '\n';
std::vector<std::thread> threads(cpus);
std::mutex mutex {};
for (auto idx = 0U; idx < cpus; ++idx) {
threads[idx] = std::thread([idx, &mutex, &cpus] {
// This mutex makes sure that we are not being suspended in the mid
// of the work
std::scoped_lock lock(mutex);
// Set CPU, without this call
// underlying os can use any CPU
auto p_id = pthread_self();
set_cpu_id(p_id, idx + 1);
std::cout << "Thread # " << std::setw(2) << idx << ": \n"
<< " - Thread Id (cxx): " << std::this_thread::get_id() << "\t"
<< " - Thread Id (native): " << p_id << '\n'
<< " - CPU Id: " << get_cpu_id(p_id, cpus) << '\n';
// Let's do some work
std::this_thread::sleep_for(2s);
});
}
for (auto& t: threads) {
t.join();
}
// No thread is running at this moment
std::cout << "Good bye!" << '\n';
return 0;
}