blob: c513246068906682ae8f99d10d24b7b3f87a296c [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
22#include "jemalloc.h"
Christopher Ferris03eebcb2014-06-13 13:57:51 -070023#include "private/bionic_macros.h"
Christopher Ferris72bbd422014-05-08 11:14:03 -070024
25void* je_pvalloc(size_t bytes) {
Elliott Hughes91570ce2014-07-10 12:34:23 -070026 size_t pagesize = getpagesize();
Dan Alberta613d0d2017-10-05 16:39:33 -070027 size_t size = __BIONIC_ALIGN(bytes, pagesize);
Christopher Ferris03eebcb2014-06-13 13:57:51 -070028 if (size < bytes) {
Yi Kong32bc0fc2018-08-02 17:31:13 -070029 return nullptr;
Christopher Ferris03eebcb2014-06-13 13:57:51 -070030 }
31 return je_memalign(pagesize, size);
Christopher Ferris72bbd422014-05-08 11:14:03 -070032}
33
34#ifdef je_memalign
35#undef je_memalign
36#endif
37
38// The man page for memalign says it fails if boundary is not a power of 2,
39// but this is not true. Both glibc and dlmalloc round up to the next power
40// of 2, so we'll do the same.
41void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
Christopher Ferris03eebcb2014-06-13 13:57:51 -070042 if (boundary != 0) {
43 if (!powerof2(boundary)) {
44 boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
Christopher Ferris72bbd422014-05-08 11:14:03 -070045 }
46 } else {
47 boundary = 1;
48 }
49 return je_memalign(boundary, size);
50}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070051
Christopher Ferrisa22f5d52019-03-01 16:40:59 -080052#ifdef je_aligned_alloc
53#undef je_aligned_alloc
54#endif
55
56// The aligned_alloc function requires that size is a multiple of alignment.
57// jemalloc doesn't enforce this, so add enforcement here.
58void* je_aligned_alloc_wrapper(size_t alignment, size_t size) {
59 if ((size % alignment) != 0) {
60 errno = EINVAL;
61 return nullptr;
62 }
63 return je_aligned_alloc(alignment, size);
64}
65
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070066int je_mallopt(int param, int value) {
67 // The only parameter we currently understand is M_DECAY_TIME.
68 if (param == M_DECAY_TIME) {
69 // Only support setting the value to 1 or 0.
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070070 ssize_t decay_time_ms;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070071 if (value) {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070072 decay_time_ms = 1000;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070073 } else {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070074 decay_time_ms = 0;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070075 }
76 // First get the total number of arenas.
77 unsigned narenas;
78 size_t sz = sizeof(unsigned);
79 if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
80 return 0;
81 }
82
83 // Set the decay time for any arenas that will be created in the future.
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070084 if (je_mallctl("arenas.dirty_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
85 return 0;
86 }
87 if (je_mallctl("arenas.muzzy_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070088 return 0;
89 }
90
91 // Change the decay on the already existing arenas.
92 char buffer[100];
93 for (unsigned i = 0; i < narenas; i++) {
Christopher Ferrisd73a49e2018-10-19 16:03:44 -070094 snprintf(buffer, sizeof(buffer), "arena.%d.dirty_decay_ms", i);
95 if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
96 break;
97 }
98 snprintf(buffer, sizeof(buffer), "arena.%d.muzzy_decay_ms", i);
99 if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700100 break;
101 }
102 }
103 return 1;
Tim Murrayac578f22018-10-15 16:26:56 -0700104 } else if (param == M_PURGE) {
105 unsigned narenas;
106 size_t sz = sizeof(unsigned);
107 if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
108 return 0;
109 }
110 char buffer[100];
111 snprintf(buffer, sizeof(buffer), "arena.%u.purge", narenas);
112 if (je_mallctl(buffer, nullptr, nullptr, nullptr, 0) != 0) {
113 return 0;
114 }
115 return 1;
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700116 }
117 return 0;
118}