OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #include "vm/globals.h" | |
6 #if defined(TARGET_OS_LINUX) | |
7 | |
8 #include "vm/cpuinfo.h" | |
9 | |
10 #include <ctype.h> // NOLINT | |
11 #include <string.h> // NOLINT | |
12 | |
13 #include "platform/assert.h" | |
14 | |
15 namespace dart { | |
16 | |
17 char* CpuInfo::data_ = NULL; | |
18 intptr_t CpuInfo::datalen_ = 0; | |
19 | |
20 void CpuInfo::InitOnce() { | |
21 InitializeFields(); | |
22 | |
23 // Get the size of the cpuinfo file by reading it until the end. This is | |
24 // required because files under /proc do not always return a valid size | |
25 // when using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. | |
26 static const char PATHNAME[] = "/proc/cpuinfo"; | |
27 FILE* fp = fopen(PATHNAME, "r"); | |
28 if (fp != NULL) { | |
29 for (;;) { | |
30 char buffer[256]; | |
31 size_t n = fread(buffer, 1, sizeof(buffer), fp); | |
32 if (n == 0) { | |
33 break; | |
34 } | |
35 datalen_ += n; | |
36 } | |
37 fclose(fp); | |
38 } | |
39 | |
40 // Read the contents of the cpuinfo file. | |
41 data_ = new char[datalen_ + 1]; | |
42 fp = fopen(PATHNAME, "r"); | |
43 if (fp != NULL) { | |
44 for (intptr_t offset = 0; offset < datalen_; ) { | |
45 size_t n = fread(data_ + offset, 1, datalen_ - offset, fp); | |
46 if (n == 0) { | |
47 break; | |
48 } | |
49 offset += n; | |
50 } | |
51 fclose(fp); | |
52 } | |
53 | |
54 // Zero-terminate the data. | |
55 data_[datalen_] = '\0'; | |
56 } | |
57 | |
58 | |
59 static char* FieldStart(char* data, const char* field) { | |
60 // Look for first field occurrence, and ensure it starts the line. | |
61 size_t fieldlen = strlen(field); | |
62 char* p = data; | |
63 for (;;) { | |
64 p = strstr(p, field); | |
65 if (p == NULL) { | |
66 return NULL; | |
67 } | |
68 if (p == data || p[-1] == '\n') { | |
69 break; | |
70 } | |
71 p += fieldlen; | |
72 } | |
73 | |
74 // Skip to the first colon followed by a space. | |
75 p = strchr(p + fieldlen, ':'); | |
76 if (p == NULL || !isspace(p[1])) { | |
77 return NULL; | |
78 } | |
79 p += 2; | |
80 | |
81 return p; | |
82 } | |
83 | |
84 | |
85 bool CpuInfo::FieldContains(const char* field, const char* search_string) { | |
86 ASSERT(data_ != NULL); | |
87 ASSERT(search_string != NULL); | |
88 | |
89 char *p = FieldStart(data_, field); | |
90 if (p == NULL) { | |
91 return false; | |
92 } | |
93 | |
94 // Find the end of the line. | |
95 char* q = strchr(p, '\n'); | |
96 if (q == NULL) { | |
97 q = data_ + datalen_; | |
98 } | |
99 | |
100 char saved_end = *q; | |
101 *q = '\0'; | |
102 bool ret = (strcasestr(p, search_string) != NULL); | |
103 *q = saved_end; | |
104 | |
105 return ret; | |
106 } | |
107 | |
108 | |
109 // Extract the content of a the first occurrence of a given field in | |
110 // the content of the cpuinfo file and return it as a heap-allocated | |
111 // string that must be freed by the caller using delete[]. | |
112 // Return NULL if not found. | |
113 char* CpuInfo::ExtractField(const char* field) { | |
114 ASSERT(field != NULL); | |
115 ASSERT(data_ != NULL); | |
116 | |
117 char* p = FieldStart(data_, field); | |
118 if (p == NULL) { | |
119 return NULL; | |
120 } | |
121 | |
122 // Find the end of the line. | |
123 char* q = strchr(p, '\n'); | |
124 if (q == NULL) { | |
125 q = data_ + datalen_; | |
126 } | |
127 | |
128 intptr_t len = q - p; | |
129 char *result = new char[len + 1]; // plus one for null-terminator. | |
130 // Copy the line into result, leaving enough room for a null-terminator. | |
131 char saved_end = *q; | |
132 *q = '\0'; | |
133 strncpy(result, p, len); | |
134 result[len] = '\0'; | |
135 *q = saved_end; | |
136 | |
137 return result; | |
138 } | |
139 | |
140 | |
141 bool CpuInfo::HasField(const char* field) { | |
142 ASSERT(field != NULL); | |
143 ASSERT(data_ != NULL); | |
144 return (FieldStart(data_, field) != NULL); | |
145 } | |
146 | |
147 | |
148 const char* CpuInfo::fields_[kCpuInfoMax] = {0}; | |
149 void CpuInfo::InitializeFields() { | |
150 #if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) | |
151 fields_[kCpuInfoProcessor] = "vendor_id"; | |
152 fields_[kCpuInfoModel] = "model name"; | |
153 fields_[kCpuInfoFeatures] = "flags"; | |
154 #elif defined(HOST_ARCH_ARM) | |
155 fields_[kCpuInfoProcessor] = "Processor"; | |
156 fields_[kCpuInfoModel] = "Hardware"; | |
157 fields_[kCpuInfoFeatures] = "Features"; | |
158 #elif defined(HOST_ARCH_MIPS) | |
159 fields_[kCpuInfoProcessor] = "system type"; | |
160 fields_[kCpuInfoModel] = "cpu model"; | |
161 fields_[kCpuInfoFeatures] = "ASEs implemented"; | |
162 #else | |
163 #error Unrecognized target architecture | |
164 #endif | |
165 } | |
166 | |
167 } // namespace dart | |
168 | |
169 #endif // defined(TARGET_OS_LINUX) | |
OLD | NEW |