1972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// Copyright (c) 2013, Google Inc. 2972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// All rights reserved. 3972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// 4972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// Redistribution and use in source and binary forms, with or without 5972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// modification, are permitted provided that the following conditions are 6972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// met: 7972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// 8972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// * Redistributions of source code must retain the above copyright 9972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// notice, this list of conditions and the following disclaimer. 10972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// * Redistributions in binary form must reproduce the above 11972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// copyright notice, this list of conditions and the following disclaimer 12972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// in the documentation and/or other materials provided with the 13972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// distribution. 14972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// * Neither the name of Google Inc. nor the names of its 15972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// contributors may be used to endorse or promote products derived from 16972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// this software without specific prior written permission. 17972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// 18972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 30972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#ifndef CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_ 31972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#define CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_ 32972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 33972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#include <stdint.h> 34972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#include <assert.h> 35972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#include <string.h> 36972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 37972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#include "common/linux/linux_libc_support.h" 38972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#include "third_party/lss/linux_syscall_support.h" 39972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 40972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.orgnamespace google_breakpad { 41972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 42972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// Helper class used to model a set of CPUs, as read from sysfs 43972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// files like /sys/devices/system/cpu/present 44972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org// See See http://www.kernel.org/doc/Documentation/cputopology.txt 45972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.orgclass CpuSet { 46972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.orgpublic: 47972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // The maximum number of supported CPUs. 48972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org static const size_t kMaxCpus = 1024; 49972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 50972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org CpuSet() { 51972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org my_memset(mask_, 0, sizeof(mask_)); 52972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 53972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 54972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Parse a sysfs file to extract the corresponding CPU set. 55972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org bool ParseSysFile(int fd) { 56972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org char buffer[512]; 57972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org int ret = sys_read(fd, buffer, sizeof(buffer)-1); 58972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org if (ret < 0) 59972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org return false; 60972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 61972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org buffer[ret] = '\0'; 62972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 63972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Expected format: comma-separated list of items, where each 64972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // item can be a decimal integer, or two decimal integers separated 65972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // by a dash. 66972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // E.g.: 67972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // 0 68972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // 0,1,2,3 69972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // 0-3 70972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // 1,10-23 71972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org const char* p = buffer; 72972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org const char* p_end = p + ret; 73972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org while (p < p_end) { 74972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Skip leading space, if any 75972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org while (p < p_end && my_isspace(*p)) 76972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org p++; 77972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 78972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Find start and size of current item. 79972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org const char* item = p; 80972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org size_t item_len = static_cast<size_t>(p_end - p); 81972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org const char* item_next = 82972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org static_cast<const char*>(my_memchr(p, ',', item_len)); 83972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org if (item_next != NULL) { 84972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org p = item_next + 1; 85972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org item_len = static_cast<size_t>(item_next - item); 86972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } else { 87972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org p = p_end; 88972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org item_next = p_end; 89972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 90972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 91972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Ignore trailing spaces. 92972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org while (item_next > item && my_isspace(item_next[-1])) 93972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org item_next--; 94972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 95972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // skip empty items. 96972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org if (item_next == item) 97972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org continue; 98972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 99972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // read first decimal value. 100972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org uintptr_t start = 0; 101972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org const char* next = my_read_decimal_ptr(&start, item); 102972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org uintptr_t end = start; 103972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org if (*next == '-') 104972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org my_read_decimal_ptr(&end, next+1); 105972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 106972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org while (start <= end) 107972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org SetBit(start++); 108972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 109972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org return true; 110972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 111972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 112972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Intersect this CPU set with another one. 113972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org void IntersectWith(const CpuSet& other) { 114972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org for (size_t nn = 0; nn < kMaskWordCount; ++nn) 115972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org mask_[nn] &= other.mask_[nn]; 116972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 117972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 118972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org // Return the number of CPUs in this set. 119972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org int GetCount() { 120972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org int result = 0; 121972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org for (size_t nn = 0; nn < kMaskWordCount; ++nn) { 122972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org result += __builtin_popcount(mask_[nn]); 123972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 124972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org return result; 125972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 126972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 127972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.orgprivate: 128972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org void SetBit(uintptr_t index) { 129972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org size_t nn = static_cast<size_t>(index); 130972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org if (nn < kMaxCpus) 131972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org mask_[nn / kMaskWordBits] |= (1U << (nn % kMaskWordBits)); 132972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org } 133972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 134972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org typedef uint32_t MaskWordType; 135972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org static const size_t kMaskWordBits = 8*sizeof(MaskWordType); 136972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org static const size_t kMaskWordCount = 137972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org (kMaxCpus + kMaskWordBits - 1) / kMaskWordBits; 138972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 139972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org MaskWordType mask_[kMaskWordCount]; 140972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org}; 141972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 142972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org} // namespace google_breakpad 143972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org 144972816ca0a2c53907b4a75c8351bed0802c9e91bdigit@chromium.org#endif // CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_ 145