am 4756afe3
: Merge "Implement malloc_info(3)."
* commit '4756afe3d5017b50c89761c47f0da17a6799c81e': Implement malloc_info(3).
This commit is contained in:
commit
a2dcd9449e
@ -134,6 +134,7 @@ libc_bionic_src_files := \
|
||||
bionic/link.cpp \
|
||||
bionic/locale.cpp \
|
||||
bionic/lstat.cpp \
|
||||
bionic/malloc_info.cpp \
|
||||
bionic/mbrtoc16.cpp \
|
||||
bionic/mbrtoc32.cpp \
|
||||
bionic/mbstate.cpp \
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "dlmalloc.h"
|
||||
|
||||
#include "malloc.h"
|
||||
#include "private/bionic_prctl.h"
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
@ -54,3 +55,25 @@ static void* named_anonymous_mmap(size_t length) {
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map, length, "libc_malloc");
|
||||
return map;
|
||||
}
|
||||
|
||||
// Since dlmalloc isn't the default, we'll leave this unimplemented for now. If
|
||||
// we decide we need it later, we can fill it in.
|
||||
size_t __mallinfo_narenas() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t __mallinfo_nbins() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mallinfo __mallinfo_arena_info(size_t) {
|
||||
struct mallinfo mi;
|
||||
memset(&mi, 0, sizeof(mi));
|
||||
return mi;
|
||||
}
|
||||
|
||||
struct mallinfo __mallinfo_bin_info(size_t, size_t) {
|
||||
struct mallinfo mi;
|
||||
memset(&mi, 0, sizeof(mi));
|
||||
return mi;
|
||||
}
|
||||
|
94
libc/bionic/malloc_info.cpp
Normal file
94
libc/bionic/malloc_info.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 "malloc_info.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include "private/bionic_macros.h"
|
||||
|
||||
class __LIBC_HIDDEN__ Elem {
|
||||
public:
|
||||
// name must be valid throughout lifetime of the object.
|
||||
explicit Elem(FILE* fp, const char* name,
|
||||
const char* attr_fmt = nullptr, ...) {
|
||||
this->fp = fp;
|
||||
this->name = name;
|
||||
|
||||
fprintf(fp, "<%s", name);
|
||||
if (attr_fmt != nullptr) {
|
||||
va_list args;
|
||||
va_start(args, attr_fmt);
|
||||
fputc(' ', fp);
|
||||
vfprintf(fp, attr_fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
fputc('>', fp);
|
||||
}
|
||||
|
||||
~Elem() noexcept {
|
||||
fprintf(fp, "</%s>", name);
|
||||
}
|
||||
|
||||
void contents(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(fp, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* fp;
|
||||
const char* name;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Elem);
|
||||
};
|
||||
|
||||
int malloc_info(int options, FILE* fp) {
|
||||
if (options != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Elem root(fp, "malloc", "version=\"jemalloc-1\"");
|
||||
|
||||
// Dump all of the large allocations in the arenas.
|
||||
for (size_t i = 0; i < __mallinfo_narenas(); i++) {
|
||||
struct mallinfo mi = __mallinfo_arena_info(i);
|
||||
if (mi.hblkhd != 0) {
|
||||
Elem arena_elem(fp, "heap", "nr=\"%d\"", i);
|
||||
{
|
||||
Elem(fp, "allocated-large").contents("%zu", mi.ordblks);
|
||||
Elem(fp, "allocated-huge").contents("%zu", mi.uordblks);
|
||||
Elem(fp, "allocated-bins").contents("%zu", mi.fsmblks);
|
||||
|
||||
size_t total = 0;
|
||||
for (size_t j = 0; j < __mallinfo_nbins(); j++) {
|
||||
struct mallinfo mi = __mallinfo_bin_info(i, j);
|
||||
if (mi.ordblks != 0) {
|
||||
Elem bin_elem(fp, "bin", "nr=\"%d\"", j);
|
||||
Elem(fp, "allocated").contents("%zu", mi.ordblks);
|
||||
Elem(fp, "nmalloc").contents("%zu", mi.uordblks);
|
||||
Elem(fp, "ndalloc").contents("%zu", mi.fordblks);
|
||||
total += mi.ordblks;
|
||||
}
|
||||
}
|
||||
Elem(fp, "bins-total").contents("%zu", total);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
32
libc/bionic/malloc_info.h
Normal file
32
libc/bionic/malloc_info.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBC_BIONIC_MALLOC_INFO_H_
|
||||
#define LIBC_BIONIC_MALLOC_INFO_H_
|
||||
|
||||
#include <malloc.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
__LIBC_HIDDEN__ size_t __mallinfo_narenas();
|
||||
__LIBC_HIDDEN__ size_t __mallinfo_nbins();
|
||||
__LIBC_HIDDEN__ struct mallinfo __mallinfo_arena_info(size_t);
|
||||
__LIBC_HIDDEN__ struct mallinfo __mallinfo_bin_info(size_t, size_t);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // LIBC_BIONIC_MALLOC_INFO_H_
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
@ -53,6 +54,27 @@ struct mallinfo {
|
||||
|
||||
extern struct mallinfo mallinfo(void);
|
||||
|
||||
/*
|
||||
* XML structure for malloc_info(3) is in the following format:
|
||||
*
|
||||
* <malloc version="jemalloc-1">
|
||||
* <heap nr="INT">
|
||||
* <allocated-large>INT</allocated-large>
|
||||
* <allocated-huge>INT</allocated-huge>
|
||||
* <allocated-bins>INT</allocated-bins>
|
||||
* <bins-total>INT</bins-total>
|
||||
* <bin nr="INT">
|
||||
* <allocated>INT</allocated>
|
||||
* <nmalloc>INT</nmalloc>
|
||||
* <ndalloc>INT</ndalloc>
|
||||
* </bin>
|
||||
* <!-- more bins -->
|
||||
* </heap>
|
||||
* <!-- more heaps -->
|
||||
* </malloc>
|
||||
*/
|
||||
extern int malloc_info(int, FILE *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* LIBC_INCLUDE_MALLOC_H_ */
|
||||
|
@ -130,6 +130,7 @@ libBionicStandardTests_cppflags := \
|
||||
|
||||
libBionicStandardTests_c_includes := \
|
||||
bionic/libc \
|
||||
external/tinyxml2 \
|
||||
|
||||
libBionicStandardTests_ldlibs_host := \
|
||||
-lrt \
|
||||
@ -243,6 +244,10 @@ include $(LOCAL_PATH)/Android.build.mk
|
||||
bionic-unit-tests_whole_static_libraries := \
|
||||
libBionicTests \
|
||||
|
||||
bionic-unit-tests_static_libraries := \
|
||||
libtinyxml2 \
|
||||
liblog \
|
||||
|
||||
bionic-unit-tests_src_files := \
|
||||
atexit_test.cpp \
|
||||
dlext_test.cpp \
|
||||
@ -280,6 +285,8 @@ bionic-unit-tests-static_static_libraries := \
|
||||
libm \
|
||||
libc \
|
||||
libstdc++ \
|
||||
libtinyxml2 \
|
||||
liblog \
|
||||
|
||||
bionic-unit-tests-static_force_static_executable := true
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include "private/bionic_config.h"
|
||||
|
||||
TEST(malloc, malloc_std) {
|
||||
@ -322,3 +324,51 @@ TEST(malloc, valloc_overflow) {
|
||||
ASSERT_EQ(NULL, valloc(SIZE_MAX));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(malloc, malloc_info) {
|
||||
#ifdef __BIONIC__
|
||||
char* buf;
|
||||
size_t bufsize;
|
||||
FILE* memstream = open_memstream(&buf, &bufsize);
|
||||
ASSERT_NE(nullptr, memstream);
|
||||
ASSERT_EQ(0, malloc_info(0, memstream));
|
||||
ASSERT_EQ(0, fclose(memstream));
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf));
|
||||
|
||||
auto root = doc.FirstChildElement();
|
||||
ASSERT_NE(nullptr, root);
|
||||
ASSERT_STREQ("malloc", root->Name());
|
||||
ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
|
||||
|
||||
auto arena = root->FirstChildElement();
|
||||
for (; arena != nullptr; arena = arena->NextSiblingElement()) {
|
||||
int val;
|
||||
|
||||
ASSERT_STREQ("heap", arena->Name());
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
arena->FirstChildElement("allocated-large")->QueryIntText(&val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
arena->FirstChildElement("bins-total")->QueryIntText(&val));
|
||||
|
||||
auto bin = arena->FirstChildElement("bin");
|
||||
for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
|
||||
if (strcmp(bin->Name(), "bin") == 0) {
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
bin->FirstChildElement("allocated")->QueryIntText(&val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
bin->FirstChildElement("nmalloc")->QueryIntText(&val));
|
||||
ASSERT_EQ(tinyxml2::XML_SUCCESS,
|
||||
bin->FirstChildElement("ndalloc")->QueryIntText(&val));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user