Add functions in sysinfo.h.
Bug: 17703902 Change-Id: I699d12d76a8fc483c919be730c2ac63641b71a1d
This commit is contained in:
parent
661423a453
commit
9d93986481
@ -213,6 +213,7 @@ libc_bionic_src_files := \
|
||||
bionic/stubs.cpp \
|
||||
bionic/symlink.cpp \
|
||||
bionic/sysconf.cpp \
|
||||
bionic/sysinfo.cpp \
|
||||
bionic/syslog.cpp \
|
||||
bionic/sys_siglist.c \
|
||||
bionic/sys_signame.c \
|
||||
|
@ -26,20 +26,17 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h> // For FOPEN_MAX.
|
||||
#include <string.h>
|
||||
#include <sys/sysconf.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "private/bionic_tls.h"
|
||||
#include "private/ScopedReaddir.h"
|
||||
|
||||
/* seems to be the default on Linux, per the GLibc sources and my own digging */
|
||||
|
||||
@ -68,81 +65,6 @@
|
||||
#define SYSTEM_2_UPE -1 /* No UPE for you ! (User Portability Utilities) */
|
||||
#define SYSTEM_2_VERSION -1 /* No posix command-line tools */
|
||||
|
||||
static bool __matches_cpuN(const char* s) {
|
||||
// The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
|
||||
unsigned cpu;
|
||||
char dummy;
|
||||
return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
|
||||
}
|
||||
|
||||
static int __sysconf_nprocessors_conf() {
|
||||
// On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
|
||||
// from there. This method works on both.
|
||||
ScopedReaddir reader("/sys/devices/system/cpu");
|
||||
if (reader.IsBad()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
dirent* entry;
|
||||
while ((entry = reader.ReadEntry()) != NULL) {
|
||||
if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int __sysconf_nprocessors_onln() {
|
||||
FILE* fp = fopen("/proc/stat", "re");
|
||||
if (fp == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
char buf[256];
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
// Extract just the first word from the line.
|
||||
// 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
|
||||
char* p = strchr(buf, ' ');
|
||||
if (p != NULL) {
|
||||
*p = 0;
|
||||
}
|
||||
if (__matches_cpuN(buf)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int __get_meminfo(const char* pattern) {
|
||||
FILE* fp = fopen("/proc/meminfo", "re");
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result = -1;
|
||||
char buf[256];
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
long total;
|
||||
if (sscanf(buf, pattern, &total) == 1) {
|
||||
result = (int) (total / (PAGE_SIZE/1024));
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int __sysconf_phys_pages() {
|
||||
return __get_meminfo("MemTotal: %ld kB");
|
||||
}
|
||||
|
||||
static int __sysconf_avphys_pages() {
|
||||
return __get_meminfo("MemFree: %ld kB");
|
||||
}
|
||||
|
||||
static int __sysconf_monotonic_clock() {
|
||||
timespec t;
|
||||
int rc = clock_getres(CLOCK_MONOTONIC, &t);
|
||||
@ -244,10 +166,10 @@ long sysconf(int name) {
|
||||
//case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
|
||||
case _SC_MONOTONIC_CLOCK: return __sysconf_monotonic_clock();
|
||||
case _SC_NPROCESSORS_CONF: return __sysconf_nprocessors_conf();
|
||||
case _SC_NPROCESSORS_ONLN: return __sysconf_nprocessors_onln();
|
||||
case _SC_PHYS_PAGES: return __sysconf_phys_pages();
|
||||
case _SC_AVPHYS_PAGES: return __sysconf_avphys_pages();
|
||||
case _SC_NPROCESSORS_CONF: return get_nprocs_conf();
|
||||
case _SC_NPROCESSORS_ONLN: return get_nprocs();
|
||||
case _SC_PHYS_PAGES: return get_phys_pages();
|
||||
case _SC_AVPHYS_PAGES: return get_avphys_pages();
|
||||
|
||||
default:
|
||||
// Posix says EINVAL is the only error that shall be returned,
|
||||
|
111
libc/bionic/sysinfo.cpp
Normal file
111
libc/bionic/sysinfo.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private/ScopedReaddir.h"
|
||||
|
||||
static bool __matches_cpuN(const char* s) {
|
||||
// The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
|
||||
unsigned cpu;
|
||||
char dummy;
|
||||
return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
|
||||
}
|
||||
|
||||
int get_nprocs_conf() {
|
||||
// On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
|
||||
// from there. This method works on both.
|
||||
ScopedReaddir reader("/sys/devices/system/cpu");
|
||||
if (reader.IsBad()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
dirent* entry;
|
||||
while ((entry = reader.ReadEntry()) != NULL) {
|
||||
if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_nprocs() {
|
||||
FILE* fp = fopen("/proc/stat", "re");
|
||||
if (fp == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
char buf[256];
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
// Extract just the first word from the line.
|
||||
// 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
|
||||
char* p = strchr(buf, ' ');
|
||||
if (p != NULL) {
|
||||
*p = 0;
|
||||
}
|
||||
if (__matches_cpuN(buf)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int __get_meminfo(const char* pattern) {
|
||||
FILE* fp = fopen("/proc/meminfo", "re");
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result = -1;
|
||||
char buf[256];
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
long total;
|
||||
if (sscanf(buf, pattern, &total) == 1) {
|
||||
result = (int) (total / (PAGE_SIZE/1024));
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
long get_phys_pages() {
|
||||
return __get_meminfo("MemTotal: %ld kB");
|
||||
}
|
||||
|
||||
long get_avphys_pages() {
|
||||
return __get_meminfo("MemFree: %ld kB");
|
||||
}
|
@ -33,7 +33,15 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern int sysinfo (struct sysinfo *info);
|
||||
int sysinfo(struct sysinfo* info);
|
||||
|
||||
int get_nprocs_conf(void);
|
||||
|
||||
int get_nprocs(void);
|
||||
|
||||
long get_phys_pages(void);
|
||||
|
||||
long get_avphys_pages(void);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
@ -98,6 +98,7 @@ libBionicStandardTests_src_files := \
|
||||
sys_stat_test.cpp \
|
||||
sys_statvfs_test.cpp \
|
||||
sys_syscall_test.cpp \
|
||||
sys_sysinfo_test.cpp \
|
||||
sys_time_test.cpp \
|
||||
sys_types_test.cpp \
|
||||
sys_vfs_test.cpp \
|
||||
|
33
tests/sys_sysinfo_test.cpp
Normal file
33
tests/sys_sysinfo_test.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
TEST(sys_sysinfo, smoke) {
|
||||
int nprocessor = get_nprocs();
|
||||
ASSERT_GT(nprocessor, 0);
|
||||
|
||||
int nprocessor_conf = get_nprocs_conf();
|
||||
ASSERT_GE(nprocessor_conf, nprocessor);
|
||||
|
||||
long avail_phys_pages = get_avphys_pages();
|
||||
ASSERT_GT(avail_phys_pages, 0);
|
||||
|
||||
long phys_pages = get_phys_pages();
|
||||
ASSERT_GE(phys_pages, avail_phys_pages);
|
||||
}
|
Loading…
Reference in New Issue
Block a user