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/link.cpp \
|
||||||
bionic/locale.cpp \
|
bionic/locale.cpp \
|
||||||
bionic/lstat.cpp \
|
bionic/lstat.cpp \
|
||||||
|
bionic/malloc_info.cpp \
|
||||||
bionic/mbrtoc16.cpp \
|
bionic/mbrtoc16.cpp \
|
||||||
bionic/mbrtoc32.cpp \
|
bionic/mbrtoc32.cpp \
|
||||||
bionic/mbstate.cpp \
|
bionic/mbstate.cpp \
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "dlmalloc.h"
|
#include "dlmalloc.h"
|
||||||
|
|
||||||
|
#include "malloc.h"
|
||||||
#include "private/bionic_prctl.h"
|
#include "private/bionic_prctl.h"
|
||||||
#include "private/libc_logging.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");
|
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map, length, "libc_malloc");
|
||||||
return map;
|
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 <sys/cdefs.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
@ -53,6 +54,27 @@ struct mallinfo {
|
|||||||
|
|
||||||
extern struct mallinfo mallinfo(void);
|
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
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* LIBC_INCLUDE_MALLOC_H_ */
|
#endif /* LIBC_INCLUDE_MALLOC_H_ */
|
||||||
|
@ -130,6 +130,7 @@ libBionicStandardTests_cppflags := \
|
|||||||
|
|
||||||
libBionicStandardTests_c_includes := \
|
libBionicStandardTests_c_includes := \
|
||||||
bionic/libc \
|
bionic/libc \
|
||||||
|
external/tinyxml2 \
|
||||||
|
|
||||||
libBionicStandardTests_ldlibs_host := \
|
libBionicStandardTests_ldlibs_host := \
|
||||||
-lrt \
|
-lrt \
|
||||||
@ -243,6 +244,10 @@ include $(LOCAL_PATH)/Android.build.mk
|
|||||||
bionic-unit-tests_whole_static_libraries := \
|
bionic-unit-tests_whole_static_libraries := \
|
||||||
libBionicTests \
|
libBionicTests \
|
||||||
|
|
||||||
|
bionic-unit-tests_static_libraries := \
|
||||||
|
libtinyxml2 \
|
||||||
|
liblog \
|
||||||
|
|
||||||
bionic-unit-tests_src_files := \
|
bionic-unit-tests_src_files := \
|
||||||
atexit_test.cpp \
|
atexit_test.cpp \
|
||||||
dlext_test.cpp \
|
dlext_test.cpp \
|
||||||
@ -280,6 +285,8 @@ bionic-unit-tests-static_static_libraries := \
|
|||||||
libm \
|
libm \
|
||||||
libc \
|
libc \
|
||||||
libstdc++ \
|
libstdc++ \
|
||||||
|
libtinyxml2 \
|
||||||
|
liblog \
|
||||||
|
|
||||||
bionic-unit-tests-static_force_static_executable := true
|
bionic-unit-tests-static_force_static_executable := true
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
#include "private/bionic_config.h"
|
#include "private/bionic_config.h"
|
||||||
|
|
||||||
TEST(malloc, malloc_std) {
|
TEST(malloc, malloc_std) {
|
||||||
@ -322,3 +324,51 @@ TEST(malloc, valloc_overflow) {
|
|||||||
ASSERT_EQ(NULL, valloc(SIZE_MAX));
|
ASSERT_EQ(NULL, valloc(SIZE_MAX));
|
||||||
}
|
}
|
||||||
#endif
|
#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…
x
Reference in New Issue
Block a user