1 //////////////////////////////////////////////////////////////////////////////// 2 // Copyright (c) 2007-2015 Hartmut Kaiser 3 // Copyright (c) 2008-2009 Chirag Dekate, Anshul Tandon 4 // Copyright (c) 2012-2013 Thomas Heller 5 // 6 // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 //////////////////////////////////////////////////////////////////////////////// 9 10 #ifndef HPX_RUNTIME_THREADS_CPU_MASK_HPP 11 #define HPX_RUNTIME_THREADS_CPU_MASK_HPP 12 13 #include <hpx/config.hpp> 14 #include <hpx/util/assert.hpp> 15 16 #include <climits> 17 #include <cstddef> 18 #include <cstdint> 19 #include <string> 20 21 #if defined(HPX_HAVE_MORE_THAN_64_THREADS) || (defined(HPX_HAVE_MAX_CPU_COUNT) \ 22 && HPX_HAVE_MAX_CPU_COUNT > 64) 23 # if defined(HPX_HAVE_MAX_CPU_COUNT) 24 # include <bitset> 25 # else 26 # include <boost/dynamic_bitset.hpp> 27 # endif 28 #endif 29 30 namespace hpx { namespace threads 31 { 32 /// \cond NOINTERNAL 33 #if !defined(HPX_HAVE_MORE_THAN_64_THREADS) || (defined(HPX_HAVE_MAX_CPU_COUNT) \ 34 && HPX_HAVE_MAX_CPU_COUNT <= 64) 35 typedef std::uint64_t mask_type; 36 typedef std::uint64_t mask_cref_type; 37 bits(std::size_t idx)38 inline std::uint64_t bits(std::size_t idx) 39 { 40 HPX_ASSERT(idx < CHAR_BIT * sizeof(mask_type)); 41 return std::uint64_t(1) << idx; 42 } 43 any(mask_cref_type mask)44 inline bool any(mask_cref_type mask) 45 { 46 return mask != 0; 47 } 48 not_(mask_cref_type mask)49 inline mask_type not_(mask_cref_type mask) 50 { 51 return ~mask; 52 } 53 test(mask_cref_type mask,std::size_t idx)54 inline bool test(mask_cref_type mask, std::size_t idx) 55 { 56 HPX_ASSERT(idx < CHAR_BIT * sizeof(mask_type)); 57 return (bits(idx) & mask) != 0; 58 } 59 set(mask_type & mask,std::size_t idx)60 inline void set(mask_type& mask, std::size_t idx) 61 { 62 HPX_ASSERT(idx < CHAR_BIT * sizeof(mask_type)); 63 mask |= bits(idx); 64 } 65 unset(mask_type & mask,std::size_t idx)66 inline void unset(mask_type& mask, std::size_t idx) 67 { 68 HPX_ASSERT(idx < CHAR_BIT * sizeof(mask_type)); 69 mask &= not_(bits(idx)); 70 } 71 mask_size(mask_cref_type)72 inline std::size_t mask_size(mask_cref_type /*mask*/) 73 { 74 return CHAR_BIT * sizeof(mask_type); 75 } 76 resize(mask_type &,std::size_t s)77 inline void resize(mask_type& /*mask*/, std::size_t s) 78 { 79 HPX_ASSERT(s <= CHAR_BIT * sizeof(mask_type)); 80 } 81 find_first(mask_cref_type mask)82 inline std::size_t find_first(mask_cref_type mask) 83 { 84 if (mask) { 85 std::size_t c = 0; // Will count mask's trailing zero bits. 86 87 // Set mask's trailing 0s to 1s and zero rest. 88 mask = (mask ^ (mask - 1)) >> 1; 89 for (/**/; mask; ++c) 90 mask >>= 1; 91 92 return c; 93 } 94 return ~std::size_t(0); 95 } 96 equal(mask_cref_type lhs,mask_cref_type rhs,std::size_t=0)97 inline bool equal(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 98 { 99 return lhs == rhs; 100 } 101 102 // return true if at least one of the masks has a bit set bit_or(mask_cref_type lhs,mask_cref_type rhs,std::size_t=0)103 inline bool bit_or(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 104 { 105 return (lhs | rhs) != 0; 106 } 107 108 // return true if at least one bit is set in both masks bit_and(mask_cref_type lhs,mask_cref_type rhs,std::size_t=0)109 inline bool bit_and(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 110 { 111 return (lhs & rhs) != 0; 112 } 113 114 // returns the number of bits set 115 // taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan count(mask_cref_type mask)116 inline std::size_t count(mask_cref_type mask) 117 { 118 std::size_t c; // c accumulates the total bits set in v 119 for (c = 0; mask; c++) 120 { 121 mask &= mask - 1; // clear the least significant bit set 122 } 123 return c; 124 } 125 reset(mask_type & mask)126 inline void reset(mask_type& mask) 127 { 128 mask = 0ull; 129 } 130 131 #define HPX_CPU_MASK_PREFIX "0x" 132 133 #else 134 # if defined(HPX_HAVE_MAX_CPU_COUNT) 135 typedef std::bitset<HPX_HAVE_MAX_CPU_COUNT> mask_type; 136 typedef std::bitset<HPX_HAVE_MAX_CPU_COUNT> const& mask_cref_type; 137 # else 138 typedef boost::dynamic_bitset<std::uint64_t> mask_type; 139 typedef boost::dynamic_bitset<std::uint64_t> const& mask_cref_type; 140 # endif 141 142 inline bool any(mask_cref_type mask) 143 { 144 return mask.any(); 145 } 146 147 inline mask_type not_(mask_cref_type mask) 148 { 149 return ~mask; 150 } 151 152 inline bool test(mask_cref_type mask, std::size_t idx) 153 { 154 return mask.test(idx); 155 } 156 157 inline void set(mask_type& mask, std::size_t idx) 158 { 159 mask.set(idx); 160 } 161 162 inline void unset(mask_type& mask, std::size_t idx) 163 { 164 mask.set(idx, 0); 165 } 166 167 inline std::size_t mask_size(mask_cref_type mask) 168 { 169 return mask.size(); 170 } 171 172 inline void resize(mask_type& mask, std::size_t s) 173 { 174 # if defined(HPX_HAVE_MAX_CPU_COUNT) 175 HPX_ASSERT(s <= mask.size()); 176 # else 177 return mask.resize(s); 178 # endif 179 } 180 181 inline std::size_t find_first(mask_cref_type mask) 182 { 183 # if defined(HPX_HAVE_MAX_CPU_COUNT) 184 if (mask.any()) 185 { 186 for (std::size_t i = 0; i != HPX_HAVE_MAX_CPU_COUNT; ++i) 187 { 188 if (mask[i]) 189 return i; 190 } 191 } 192 return ~std::size_t(0); 193 # else 194 return mask.find_first(); 195 # endif 196 } 197 198 # if defined(HPX_HAVE_MAX_CPU_COUNT) 199 #define HPX_CPU_MASK_PREFIX "0b" 200 #else 201 #define HPX_CPU_MASK_PREFIX "0x" 202 #endif 203 204 inline bool equal(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 205 { 206 return lhs == rhs; 207 } 208 209 // return true if at least one of the masks has a bit set 210 inline bool bit_or(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 211 { 212 return (lhs | rhs).any(); 213 } 214 215 // return true if at least one bit is set in both masks 216 inline bool bit_and(mask_cref_type lhs, mask_cref_type rhs, std::size_t = 0) 217 { 218 return (lhs & rhs).any(); 219 } 220 221 // returns the number of bits set 222 inline std::size_t count(mask_cref_type mask) 223 { 224 return mask.count(); 225 } 226 227 inline void reset(mask_type& mask) 228 { 229 mask.reset(); 230 } 231 232 #endif 233 234 HPX_API_EXPORT std::string to_string(mask_cref_type); 235 /// \endcond 236 }} 237 238 #endif /*HPX_RUNTIME_THREADS_CPU_MASK_HPP*/ 239