xref: /libuv/test/test-thread-affinity.c (revision 011a1ac1)
1 /* Copyright libuv project contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "task.h"
24 
25 #include <string.h>
26 
27 #ifndef NO_CPU_AFFINITY
28 
check_affinity(void * arg)29 static void check_affinity(void* arg) {
30   int r;
31   char* cpumask;
32   int cpumasksize;
33   uv_thread_t tid;
34 
35   cpumask = (char*)arg;
36   cpumasksize = uv_cpumask_size();
37   ASSERT_GT(cpumasksize, 0);
38   tid = uv_thread_self();
39   r = uv_thread_setaffinity(&tid, cpumask, NULL, cpumasksize);
40   ASSERT_OK(r);
41   r = uv_thread_setaffinity(&tid, cpumask + cpumasksize, cpumask, cpumasksize);
42   ASSERT_OK(r);
43 }
44 
45 
TEST_IMPL(thread_affinity)46 TEST_IMPL(thread_affinity) {
47   int t1first;
48   int t1second;
49   int t2first;
50   int t2second;
51   int cpumasksize;
52   char* cpumask;
53   int ncpus;
54   int r;
55   int c;
56   int i;
57   uv_thread_t threads[3];
58 
59 #ifdef _WIN32
60   /* uv_thread_self isn't defined for the main thread on Windows */
61   threads[0] = GetCurrentThread();
62 #else
63   threads[0] = uv_thread_self();
64 #endif
65   cpumasksize = uv_cpumask_size();
66   ASSERT_GT(cpumasksize, 0);
67 
68   cpumask = calloc(4 * cpumasksize, 1);
69   ASSERT(cpumask);
70 
71   r = uv_thread_getaffinity(&threads[0], cpumask, cpumasksize);
72   ASSERT_OK(r);
73   ASSERT(cpumask[0] && "test must be run with cpu 0 affinity");
74   ncpus = 0;
75   while (cpumask[++ncpus]) { }
76   memset(cpumask, 0, 4 * cpumasksize);
77 
78   t1first = cpumasksize * 0;
79   t1second = cpumasksize * 1;
80   t2first = cpumasksize * 2;
81   t2second = cpumasksize * 3;
82 
83   cpumask[t1second + 0] = 1;
84   cpumask[t2first + 0] = 1;
85   cpumask[t1first + (ncpus >= 2)] = 1;
86   cpumask[t2second + (ncpus >= 2)] = 1;
87 #ifdef __linux__
88   cpumask[t1second + 2] = 1;
89   cpumask[t2first + 2] = 1;
90   cpumask[t1first + 3] = 1;
91   cpumask[t2second + 3] = 1;
92 #else
93   if (ncpus >= 3) {
94     cpumask[t1second + 2] = 1;
95     cpumask[t2first + 2] = 1;
96   }
97   if (ncpus >= 4) {
98     cpumask[t1first + 3] = 1;
99     cpumask[t2second + 3] = 1;
100   }
101 #endif
102 
103   ASSERT_OK(uv_thread_create(threads + 1,
104                              check_affinity,
105                              &cpumask[t1first]));
106   ASSERT_OK(uv_thread_create(threads + 2,
107                              check_affinity,
108                              &cpumask[t2first]));
109   ASSERT_OK(uv_thread_join(threads + 1));
110   ASSERT_OK(uv_thread_join(threads + 2));
111 
112   ASSERT(cpumask[t1first + 0] == (ncpus == 1));
113   ASSERT(cpumask[t1first + 1] == (ncpus >= 2));
114   ASSERT_OK(cpumask[t1first + 2]);
115   ASSERT(cpumask[t1first + 3] == (ncpus >= 4));
116 
117   ASSERT_EQ(1, cpumask[t2first + 0]);
118   ASSERT_OK(cpumask[t2first + 1]);
119   ASSERT(cpumask[t2first + 2] == (ncpus >= 3));
120   ASSERT_OK(cpumask[t2first + 3]);
121 
122   c = uv_thread_getcpu();
123   ASSERT_GE(c, 0);
124 
125   memset(cpumask, 0, cpumasksize);
126   cpumask[c] = 1;
127   r = uv_thread_setaffinity(&threads[0], cpumask, NULL, cpumasksize);
128   ASSERT_OK(r);
129 
130   memset(cpumask, 0, cpumasksize);
131   r = uv_thread_getaffinity(&threads[0], cpumask, cpumasksize);
132   ASSERT_OK(r);
133   for (i = 0; i < cpumasksize; i++) {
134     if (i == c)
135       ASSERT_EQ(1, cpumask[i]);
136     else
137       ASSERT_OK(cpumask[i]);
138   }
139 
140   free(cpumask);
141 
142   return 0;
143 }
144 
145 #else
146 
TEST_IMPL(thread_affinity)147 TEST_IMPL(thread_affinity) {
148   int cpumasksize;
149   cpumasksize = uv_cpumask_size();
150   ASSERT_EQ(cpumasksize, UV_ENOTSUP);
151   return 0;
152 }
153 
154 #endif
155