// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/globals.h" #if defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) #include "vm/proccpuinfo.h" #include // NOLINT #include // NOLINT #include "platform/assert.h" namespace dart { char* ProcCpuInfo::data_ = NULL; intptr_t ProcCpuInfo::datalen_ = 0; void ProcCpuInfo::Init() { // Get the size of the cpuinfo file by reading it until the end. This is // required because files under /proc do not always return a valid size // when using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. static const char PATHNAME[] = "/proc/cpuinfo"; FILE* fp = fopen(PATHNAME, "r"); if (fp != NULL) { for (;;) { char buffer[256]; size_t n = fread(buffer, 1, sizeof(buffer), fp); if (n == 0) { break; } datalen_ += n; } fclose(fp); } // Read the contents of the cpuinfo file. data_ = reinterpret_cast(malloc(datalen_ + 1)); fp = fopen(PATHNAME, "r"); if (fp != NULL) { for (intptr_t offset = 0; offset < datalen_;) { size_t n = fread(data_ + offset, 1, datalen_ - offset, fp); if (n == 0) { break; } offset += n; } fclose(fp); } // Zero-terminate the data. data_[datalen_] = '\0'; } void ProcCpuInfo::Cleanup() { ASSERT(data_); free(data_); data_ = NULL; } char* ProcCpuInfo::FieldStart(const char* field) { // Look for first field occurrence, and ensure it starts the line. size_t fieldlen = strlen(field); char* p = data_; for (;;) { p = strstr(p, field); if (p == NULL) { return NULL; } if (p == data_ || p[-1] == '\n') { break; } p += fieldlen; } // Skip to the first colon followed by a space. p = strchr(p + fieldlen, ':'); if (p == NULL || (isspace(p[1]) == 0)) { return NULL; } p += 2; return p; } bool ProcCpuInfo::FieldContains(const char* field, const char* search_string) { ASSERT(data_ != NULL); ASSERT(search_string != NULL); char* p = FieldStart(field); if (p == NULL) { return false; } // Find the end of the line. char* q = strchr(p, '\n'); if (q == NULL) { q = data_ + datalen_; } char saved_end = *q; *q = '\0'; bool ret = (strcasestr(p, search_string) != NULL); *q = saved_end; return ret; } // Extract the content of a the first occurrence of a given field in // the content of the cpuinfo file and return it as a heap-allocated // string that must be freed by the caller using free. // Return NULL if not found. const char* ProcCpuInfo::ExtractField(const char* field) { ASSERT(field != NULL); ASSERT(data_ != NULL); char* p = FieldStart(field); if (p == NULL) { return NULL; } // Find the end of the line. char* q = strchr(p, '\n'); if (q == NULL) { q = data_ + datalen_; } intptr_t len = q - p; char* result = reinterpret_cast(malloc(len + 1)); // Copy the line into result, leaving enough room for a null-terminator. char saved_end = *q; *q = '\0'; strncpy(result, p, len); result[len] = '\0'; *q = saved_end; return result; } bool ProcCpuInfo::HasField(const char* field) { ASSERT(field != NULL); ASSERT(data_ != NULL); return (FieldStart(field) != NULL); } } // namespace dart #endif // defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID)