Planeshift
|
00001 // Copyright (c) 2013, Google Inc. 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are 00006 // met: 00007 // 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above 00011 // copyright notice, this list of conditions and the following disclaimer 00012 // in the documentation and/or other materials provided with the 00013 // distribution. 00014 // * Neither the name of Google Inc. nor the names of its 00015 // contributors may be used to endorse or promote products derived from 00016 // this software without specific prior written permission. 00017 // 00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 00030 #ifndef CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_ 00031 #define CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_ 00032 00033 #include <stdint.h> 00034 #include <assert.h> 00035 #include <string.h> 00036 00037 #include "common/linux/linux_libc_support.h" 00038 #include "third_party/lss/linux_syscall_support.h" 00039 00040 namespace google_breakpad { 00041 00042 // Helper class used to model a set of CPUs, as read from sysfs 00043 // files like /sys/devices/system/cpu/present 00044 // See See http://www.kernel.org/doc/Documentation/cputopology.txt 00045 class CpuSet { 00046 public: 00047 // The maximum number of supported CPUs. 00048 static const size_t kMaxCpus = 1024; 00049 00050 CpuSet() { 00051 my_memset(mask_, 0, sizeof(mask_)); 00052 } 00053 00054 // Parse a sysfs file to extract the corresponding CPU set. 00055 bool ParseSysFile(int fd) { 00056 char buffer[512]; 00057 int ret = sys_read(fd, buffer, sizeof(buffer)-1); 00058 if (ret < 0) 00059 return false; 00060 00061 buffer[ret] = '\0'; 00062 00063 // Expected format: comma-separated list of items, where each 00064 // item can be a decimal integer, or two decimal integers separated 00065 // by a dash. 00066 // E.g.: 00067 // 0 00068 // 0,1,2,3 00069 // 0-3 00070 // 1,10-23 00071 const char* p = buffer; 00072 const char* p_end = p + ret; 00073 while (p < p_end) { 00074 // Skip leading space, if any 00075 while (p < p_end && my_isspace(*p)) 00076 p++; 00077 00078 // Find start and size of current item. 00079 const char* item = p; 00080 size_t item_len = static_cast<size_t>(p_end - p); 00081 const char* item_next = 00082 static_cast<const char*>(my_memchr(p, ',', item_len)); 00083 if (item_next != NULL) { 00084 p = item_next + 1; 00085 item_len = static_cast<size_t>(item_next - item); 00086 } else { 00087 p = p_end; 00088 item_next = p_end; 00089 } 00090 00091 // Ignore trailing spaces. 00092 while (item_next > item && my_isspace(item_next[-1])) 00093 item_next--; 00094 00095 // skip empty items. 00096 if (item_next == item) 00097 continue; 00098 00099 // read first decimal value. 00100 uintptr_t start = 0; 00101 const char* next = my_read_decimal_ptr(&start, item); 00102 uintptr_t end = start; 00103 if (*next == '-') 00104 my_read_decimal_ptr(&end, next+1); 00105 00106 while (start <= end) 00107 SetBit(start++); 00108 } 00109 return true; 00110 } 00111 00112 // Intersect this CPU set with another one. 00113 void IntersectWith(const CpuSet& other) { 00114 for (size_t nn = 0; nn < kMaskWordCount; ++nn) 00115 mask_[nn] &= other.mask_[nn]; 00116 } 00117 00118 // Return the number of CPUs in this set. 00119 int GetCount() { 00120 int result = 0; 00121 for (size_t nn = 0; nn < kMaskWordCount; ++nn) { 00122 result += __builtin_popcount(mask_[nn]); 00123 } 00124 return result; 00125 } 00126 00127 private: 00128 void SetBit(uintptr_t index) { 00129 size_t nn = static_cast<size_t>(index); 00130 if (nn < kMaxCpus) 00131 mask_[nn / kMaskWordBits] |= (1U << (nn % kMaskWordBits)); 00132 } 00133 00134 typedef uint32_t MaskWordType; 00135 static const size_t kMaskWordBits = 8*sizeof(MaskWordType); 00136 static const size_t kMaskWordCount = 00137 (kMaxCpus + kMaskWordBits - 1) / kMaskWordBits; 00138 00139 MaskWordType mask_[kMaskWordCount]; 00140 }; 00141 00142 } // namespace google_breakpad 00143 00144 #endif // CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_