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 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 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 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