14caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert/*
24caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * Copyright (C) 2014 The Android Open Source Project
34caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert *
44caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * Licensed under the Apache License, Version 2.0 (the "License");
54caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * you may not use this file except in compliance with the License.
64caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * You may obtain a copy of the License at
74caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert *
84caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert *      http://www.apache.org/licenses/LICENSE-2.0
94caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert *
104caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * Unless required by applicable law or agreed to in writing, software
114caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * distributed under the License is distributed on an "AS IS" BASIS,
124caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * See the License for the specific language governing permissions and
144caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert * limitations under the License.
154caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert */
164caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
174caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert#include "malloc_info.h"
184caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
194caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert#include <errno.h>
204caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert#include "private/bionic_macros.h"
214caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
224caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albertclass __LIBC_HIDDEN__ Elem {
234caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albertpublic:
244caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  // name must be valid throughout lifetime of the object.
254caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  explicit Elem(FILE* fp, const char* name,
264caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert                const char* attr_fmt = nullptr, ...) {
274caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    this->fp = fp;
284caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    this->name = name;
294caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
304caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    fprintf(fp, "<%s", name);
314caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    if (attr_fmt != nullptr) {
324caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_list args;
334caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_start(args, attr_fmt);
344caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      fputc(' ', fp);
354caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      vfprintf(fp, attr_fmt, args);
364caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_end(args);
374caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    }
384caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    fputc('>', fp);
394caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  }
404caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
414caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  ~Elem() noexcept {
424caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    fprintf(fp, "</%s>", name);
434caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  }
444caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
454caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  void contents(const char* fmt, ...) {
464caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_list args;
474caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_start(args, fmt);
484caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      vfprintf(fp, fmt, args);
494caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      va_end(args);
504caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  }
514caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
524caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albertprivate:
534caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  FILE* fp;
544caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  const char* name;
554caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
564caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  DISALLOW_COPY_AND_ASSIGN(Elem);
574caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert};
584caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
594caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albertint malloc_info(int options, FILE* fp) {
604caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  if (options != 0) {
614caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    errno = EINVAL;
624caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    return -1;
634caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  }
644caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
654caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  Elem root(fp, "malloc", "version=\"jemalloc-1\"");
664caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
674caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  // Dump all of the large allocations in the arenas.
684caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  for (size_t i = 0; i < __mallinfo_narenas(); i++) {
694caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    struct mallinfo mi = __mallinfo_arena_info(i);
704caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    if (mi.hblkhd != 0) {
714caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      Elem arena_elem(fp, "heap", "nr=\"%d\"", i);
724caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      {
734caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        Elem(fp, "allocated-large").contents("%zu", mi.ordblks);
744caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        Elem(fp, "allocated-huge").contents("%zu", mi.uordblks);
754caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        Elem(fp, "allocated-bins").contents("%zu", mi.fsmblks);
764caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
774caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        size_t total = 0;
784caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        for (size_t j = 0; j < __mallinfo_nbins(); j++) {
794caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert          struct mallinfo mi = __mallinfo_bin_info(i, j);
804caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert          if (mi.ordblks != 0) {
814caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert            Elem bin_elem(fp, "bin", "nr=\"%d\"", j);
824caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert            Elem(fp, "allocated").contents("%zu", mi.ordblks);
834caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert            Elem(fp, "nmalloc").contents("%zu", mi.uordblks);
844caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert            Elem(fp, "ndalloc").contents("%zu", mi.fordblks);
854caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert            total += mi.ordblks;
864caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert          }
874caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        }
884caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert        Elem(fp, "bins-total").contents("%zu", total);
894caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert      }
904caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert    }
914caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  }
924caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert
934caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert  return 0;
944caa1f09770ea3e5ca22afbe8aa0900810a0dbfeDan Albert}
95