blob: 7d2f630b47a6e823bf4b4b18ef8957359a6d6e5a [file] [log] [blame]
Colin Crossbcb4ed32016-01-14 15:35:40 -08001/*
2 * Copyright (C) 2016 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
17#ifndef LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
18#define LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
19
20#include <memory>
21
22#include "android-base/macros.h"
23
Colin Crossa83881e2017-06-22 10:50:05 -070024#include "ScopedAlarm.h"
Colin Crossbcb4ed32016-01-14 15:35:40 -080025#include "bionic.h"
26#include "log.h"
Colin Crossbcb4ed32016-01-14 15:35:40 -080027
Colin Crossa83881e2017-06-22 10:50:05 -070028class DisableMallocGuard {
Colin Crossbcb4ed32016-01-14 15:35:40 -080029 public:
Colin Crossa83881e2017-06-22 10:50:05 -070030 DisableMallocGuard() : disabled_(false) {}
31 ~DisableMallocGuard() { Enable(); }
Colin Crossbcb4ed32016-01-14 15:35:40 -080032
33 void Disable() {
34 if (!disabled_) {
35 malloc_disable();
36 disabled_ = true;
37 }
38 }
39
40 void Enable() {
41 if (disabled_) {
42 malloc_enable();
43 disabled_ = false;
44 }
45 }
Colin Crossa83881e2017-06-22 10:50:05 -070046
Colin Crossbcb4ed32016-01-14 15:35:40 -080047 private:
48 DISALLOW_COPY_AND_ASSIGN(DisableMallocGuard);
49 bool disabled_;
50};
51
52// Any calls to malloc or free from this thread will deadlock as long as this
53// object is in scope. Calls to malloc from other threads may succeed (for
54// example if the allocation is satisfied out of the thread's tcache), or may
55// block until the object is destroyed.
56//
57// Don't call fork() while malloc is disabled, it needs the same locks held
58// here.
59class ScopedDisableMalloc {
60 public:
Colin Crossa83881e2017-06-22 10:50:05 -070061 ScopedDisableMalloc() { disable_malloc_.Disable(); }
Colin Crossbcb4ed32016-01-14 15:35:40 -080062
Colin Crossa83881e2017-06-22 10:50:05 -070063 ~ScopedDisableMalloc() { disable_malloc_.Enable(); }
Colin Crossbcb4ed32016-01-14 15:35:40 -080064
65 private:
66 DISALLOW_COPY_AND_ASSIGN(ScopedDisableMalloc);
67 DisableMallocGuard disable_malloc_;
68};
69
70class ScopedDisableMallocTimeout {
71 public:
Colin Crossa83881e2017-06-22 10:50:05 -070072 explicit ScopedDisableMallocTimeout(
73 std::chrono::milliseconds timeout = std::chrono::milliseconds(2000))
74 : timeout_(timeout), timed_out_(false), disable_malloc_() {
Colin Crossbcb4ed32016-01-14 15:35:40 -080075 Disable();
76 }
77
Colin Crossa83881e2017-06-22 10:50:05 -070078 ~ScopedDisableMallocTimeout() { Enable(); }
Colin Crossbcb4ed32016-01-14 15:35:40 -080079
Colin Crossa83881e2017-06-22 10:50:05 -070080 bool timed_out() { return timed_out_; }
Colin Crossbcb4ed32016-01-14 15:35:40 -080081
82 void Enable() {
83 disable_malloc_.Enable();
84 alarm_ = nullptr;
85 }
86
87 void Disable() {
88 // set up the alarm before disabling malloc so unique_ptr can be used
89 alarm_ = std::make_unique<ScopedAlarm>(timeout_, [&]() {
90 disable_malloc_.Enable();
91 timed_out_ = true;
92 });
93
94 disable_malloc_.Disable();
95 }
96
97 private:
98 DISALLOW_COPY_AND_ASSIGN(ScopedDisableMallocTimeout);
99 std::chrono::milliseconds timeout_;
100 bool timed_out_;
101 std::unique_ptr<ScopedAlarm> alarm_;
102 DisableMallocGuard disable_malloc_;
103};
104
Colin Crossa83881e2017-06-22 10:50:05 -0700105#endif // LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_