1 : // Copyright 2016 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Implementation of a background thread that that asynchronously trims the
16 : // quarantine.
17 :
18 : #ifndef SYZYGY_AGENT_ASAN_HEAP_MANAGERS_DEFERRED_FREE_THREAD_H_
19 : #define SYZYGY_AGENT_ASAN_HEAP_MANAGERS_DEFERRED_FREE_THREAD_H_
20 :
21 : #include "base/callback.h"
22 : #include "base/synchronization/condition_variable.h"
23 : #include "base/threading/platform_thread.h"
24 : #include "base/threading/thread.h"
25 :
26 : namespace agent {
27 : namespace asan {
28 : namespace heap_managers {
29 :
30 : // This object can be created by each process. It spawns a low-priority
31 : // background thread that is responsible for performing deferred work that
32 : // Free() would otherwise be doing on the critical path. The goal is to improve
33 : // responsiveness.
34 : //
35 : // As of now, this is responsible of trimming the shared quarantine. For more
36 : // information on the trimming and the different modes and colors, see
37 : // quarantine.h.
38 : //
39 : // Note that the thread must be cleanly shutdown by calling Stop before the
40 : // HeapManager is cleaned up, otherwise the callback might still be running
41 : // after the HeapManager no longer exists.
42 : class DeferredFreeThread : public base::PlatformThread::Delegate {
43 : public:
44 : typedef base::Closure Callback;
45 : // @param deferred_free_callback Callback that is called by the thread when
46 : // signaled. This callback must be valid from the moment Start is called and
47 : // until Stop is called.
48 : explicit DeferredFreeThread(Callback deferred_free_callback);
49 : ~DeferredFreeThread() override;
50 :
51 : // Starts the thread and waits until it signals that it's ready to work. Must
52 : // be called before use. Must not be called if the thread has already been
53 : // started.
54 : // @returns true if successful, false if the thread failed to be launched.
55 : bool Start();
56 :
57 : // Stops the thread and waits until it exists cleanly. Must be called before
58 : // the destruction of this object and before the callback is no longer valid.
59 : // Must not be called if the thread has not been started previously.
60 : void Stop();
61 :
62 : // Used to signal to the thread that work is required (wakes up the thread).
63 : // It avoids over signaling (slow operation) by raising a flag
64 : // (|deferred_free_signaled_|) and bailing if it's already set (flag gets
65 : // unset by the thread). It's therefore ok to call this repeatedly.
66 : void SignalWork();
67 :
68 : // @returns the thread ID.
69 E : base::PlatformThreadId deferred_free_thread_id() const {
70 E : return deferred_free_thread_id_;
71 E : }
72 :
73 : private:
74 : // Implementation of PlatformThread::Delegate:
75 : void ThreadMain() override;
76 :
77 : // Callback to the deferred free function, set by the constructor.
78 : Callback deferred_free_callback_;
79 :
80 : // Used to signal that work is ready (wakes up the background thread).
81 : base::WaitableEvent deferred_free_event_;
82 : // This atomic is set when the thread is signaled and cleared when the thread
83 : // wakes up. The objective is to limit the amount of over signaling possible.
84 : base::subtle::Atomic32 deferred_free_signaled_;
85 :
86 : // Handle to the thread, used to join the thread when stopping.
87 : base::PlatformThreadHandle deferred_free_thread_handle_;
88 :
89 : // The thread ID, can be used by callbacks to validate that they're running on
90 : // the right thread.
91 : base::PlatformThreadId deferred_free_thread_id_;
92 :
93 : // Used to signal that the background thread has spawned up and is ready to
94 : // work.
95 : base::WaitableEvent ready_event_;
96 :
97 : // Atomic that controls the execution of the background thread (loops while
98 : // this is true).
99 : base::subtle::Atomic32 enabled_;
100 :
101 : DISALLOW_COPY_AND_ASSIGN(DeferredFreeThread);
102 : };
103 :
104 : } // namespace heap_managers
105 : } // namespace asan
106 : } // namespace agent
107 :
108 : #endif // SYZYGY_AGENT_ASAN_HEAP_MANAGERS_DEFERRED_FREE_THREAD_H_
|