• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/sysinfo.h>
30 
31 #include <dirent.h>
32 #include <limits.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 #include "private/ScopedReaddir.h"
37 
__matches_cpuN(const char * s)38 static bool __matches_cpuN(const char* s) {
39   // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
40   unsigned cpu;
41   char dummy;
42   return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
43 }
44 
get_nprocs_conf()45 int get_nprocs_conf() {
46   // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
47   // from there. This method works on both.
48   ScopedReaddir reader("/sys/devices/system/cpu");
49   if (reader.IsBad()) {
50     return 1;
51   }
52 
53   int result = 0;
54   dirent* entry;
55   while ((entry = reader.ReadEntry()) != NULL) {
56     if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
57       ++result;
58     }
59   }
60   return result;
61 }
62 
get_nprocs()63 int get_nprocs() {
64   FILE* fp = fopen("/proc/stat", "re");
65   if (fp == NULL) {
66     return 1;
67   }
68 
69   int result = 0;
70   char buf[256];
71   while (fgets(buf, sizeof(buf), fp) != NULL) {
72     // Extract just the first word from the line.
73     // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
74     char* p = strchr(buf, ' ');
75     if (p != NULL) {
76       *p = 0;
77     }
78     if (__matches_cpuN(buf)) {
79       ++result;
80     }
81   }
82   fclose(fp);
83   return result;
84 }
85 
__get_meminfo_page_count(const char * pattern)86 static int __get_meminfo_page_count(const char* pattern) {
87   FILE* fp = fopen("/proc/meminfo", "re");
88   if (fp == NULL) {
89     return -1;
90   }
91 
92   int page_count = -1;
93   char buf[256];
94   while (fgets(buf, sizeof(buf), fp) != NULL) {
95     long total;
96     if (sscanf(buf, pattern, &total) == 1) {
97       page_count = static_cast<int>(total / (PAGE_SIZE / 1024));
98       break;
99     }
100   }
101   fclose(fp);
102   return page_count;
103 }
104 
get_phys_pages()105 long get_phys_pages() {
106   return __get_meminfo_page_count("MemTotal: %ld kB");
107 }
108 
get_avphys_pages()109 long get_avphys_pages() {
110   return __get_meminfo_page_count("MemFree: %ld kB");
111 }
112