blob: bc3a9dcdf1ba0cbc778711e3b6e58a9283913e17 [file] [log] [blame]
Christopher Ferris72bbd422014-05-08 11:14:03 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Christopher Ferrisa22f5d52019-03-01 16:40:59 -080017#include <errno.h>
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070018#include <malloc.h>
Christopher Ferris03eebcb2014-06-13 13:57:51 -070019#include <sys/param.h>
Christopher Ferris72bbd422014-05-08 11:14:03 -070020#include <unistd.h>
21
Christopher Ferris6c619a02019-03-01 17:59:51 -080022#include <private/MallocXmlElem.h>
23
Christopher Ferris72bbd422014-05-08 11:14:03 -070024#include "jemalloc.h"
25
26void* je_pvalloc(size_t bytes) {
Elliott Hughes91570ce2014-07-10 12:34:23 -070027 size_t pagesize = getpagesize();
Dan Alberta613d0d2017-10-05 16:39:33 -070028 size_t size = __BIONIC_ALIGN(bytes, pagesize);
Christopher Ferris03eebcb2014-06-13 13:57:51 -070029 if (size < bytes) {
Yi Kong32bc0fc2018-08-02 17:31:13 -070030 return nullptr;
Christopher Ferris03eebcb2014-06-13 13:57:51 -070031 }
32 return je_memalign(pagesize, size);
Christopher Ferris72bbd422014-05-08 11:14:03 -070033}
34
35#ifdef je_memalign
36#undef je_memalign
37#endif
38
39// The man page for memalign says it fails if boundary is not a power of 2,
40// but this is not true. Both glibc and dlmalloc round up to the next power
41// of 2, so we'll do the same.
42void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
Christopher Ferris03eebcb2014-06-13 13:57:51 -070043 if (boundary != 0) {
44 if (!powerof2(boundary)) {
45 boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
Christopher Ferris72bbd422014-05-08 11:14:03 -070046 }
47 } else {
48 boundary = 1;
49 }
50 return je_memalign(boundary, size);
51}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070052
Christopher Ferrisa22f5d52019-03-01 16:40:59 -080053#ifdef je_aligned_alloc
54#undef je_aligned_alloc
55#endif
56
57// The aligned_alloc function requires that size is a multiple of alignment.
58// jemalloc doesn't enforce this, so add enforcement here.
59void* je_aligned_alloc_wrapper(size_t alignment, size_t size) {
60 if ((size % alignment) != 0) {
61 errno = EINVAL;
62 return nullptr;
63 }
64 return je_aligned_alloc(alignment, size);
65}
66
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070067int je_mallopt(int param, int value) {
68 // The only parameter we currently understand is M_DECAY_TIME.
69 if (param == M_DECAY_TIME) {
70 // Only support setting the value to 1 or 0.
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070071 ssize_t decay_time_ms;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070072 if (value) {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070073 decay_time_ms = 1000;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070074 } else {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070075 decay_time_ms = 0;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070076 }
77 // First get the total number of arenas.
78 unsigned narenas;
79 size_t sz = sizeof(unsigned);
80 if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
81 return 0;
82 }
83
84 // Set the decay time for any arenas that will be created in the future.
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070085 if (je_mallctl("arenas.dirty_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
86 return 0;
87 }
88 if (je_mallctl("arenas.muzzy_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070089 return 0;
90 }
91
92 // Change the decay on the already existing arenas.
93 char buffer[100];
94 for (unsigned i = 0; i < narenas; i++) {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070095 snprintf(buffer, sizeof(buffer), "arena.%d.dirty_decay_ms", i);
96 if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
97 break;
98 }
99 snprintf(buffer, sizeof(buffer), "arena.%d.muzzy_decay_ms", i);
100 if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700101 break;
102 }
103 }
104 return 1;
Tim Murrayac578f22018-10-15 16:26:56 -0700105 } else if (param == M_PURGE) {
106 unsigned narenas;
107 size_t sz = sizeof(unsigned);
108 if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
109 return 0;
110 }
111 char buffer[100];
112 snprintf(buffer, sizeof(buffer), "arena.%u.purge", narenas);
113 if (je_mallctl(buffer, nullptr, nullptr, nullptr, 0) != 0) {
114 return 0;
115 }
116 return 1;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700117 }
118 return 0;
119}
Christopher Ferris6c619a02019-03-01 17:59:51 -0800120
121__BEGIN_DECLS
122
123size_t __mallinfo_narenas();
124size_t __mallinfo_nbins();
125struct mallinfo __mallinfo_arena_info(size_t);
126struct mallinfo __mallinfo_bin_info(size_t, size_t);
127
128__END_DECLS
129
130int je_malloc_info(int options, FILE* fp) {
131 if (options != 0) {
132 errno = EINVAL;
133 return -1;
134 }
135
136 MallocXmlElem root(fp, "malloc", "version=\"jemalloc-1\"");
137
138 // Dump all of the large allocations in the arenas.
139 for (size_t i = 0; i < __mallinfo_narenas(); i++) {
140 struct mallinfo mi = __mallinfo_arena_info(i);
141 if (mi.hblkhd != 0) {
142 MallocXmlElem arena_elem(fp, "heap", "nr=\"%d\"", i);
143 {
144 MallocXmlElem(fp, "allocated-large").Contents("%zu", mi.ordblks);
145 MallocXmlElem(fp, "allocated-huge").Contents("%zu", mi.uordblks);
146 MallocXmlElem(fp, "allocated-bins").Contents("%zu", mi.fsmblks);
147
148 size_t total = 0;
149 for (size_t j = 0; j < __mallinfo_nbins(); j++) {
150 struct mallinfo mi = __mallinfo_bin_info(i, j);
151 if (mi.ordblks != 0) {
152 MallocXmlElem bin_elem(fp, "bin", "nr=\"%d\"", j);
153 MallocXmlElem(fp, "allocated").Contents("%zu", mi.ordblks);
154 MallocXmlElem(fp, "nmalloc").Contents("%zu", mi.uordblks);
155 MallocXmlElem(fp, "ndalloc").Contents("%zu", mi.fordblks);
156 total += mi.ordblks;
157 }
158 }
159 MallocXmlElem(fp, "bins-total").Contents("%zu", total);
160 }
161 }
162 }
163
164 return 0;
165}