1 /*
2  * Copyright (C) 2005 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 ANDROID_STRONG_POINTER_H
18 #define ANDROID_STRONG_POINTER_H
19 
20 #include <functional>
21 #include <type_traits>  // for common_type.
22 
23 // ---------------------------------------------------------------------------
24 namespace android {
25 
26 template<typename T> class wp;
27 
28 // ---------------------------------------------------------------------------
29 
30 template<typename T>
31 class sp {
32 public:
sp()33     inline sp() : m_ptr(nullptr) { }
34 
35     // TODO: switch everyone to using this over new, and make RefBase operator
36     // new private to that class so that we can avoid RefBase being used with
37     // other memory management mechanisms.
38     template <typename... Args>
39     static inline sp<T> make(Args&&... args);
40 
41     sp(T* other);  // NOLINT(implicit)
42     sp(const sp<T>& other);
43     sp(sp<T>&& other) noexcept;
44     template<typename U> sp(U* other);  // NOLINT(implicit)
45     template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
46     template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
47 
48     ~sp();
49 
50     // Assignment
51 
52     sp& operator = (T* other);
53     sp& operator = (const sp<T>& other);
54     sp& operator=(sp<T>&& other) noexcept;
55 
56     template<typename U> sp& operator = (const sp<U>& other);
57     template<typename U> sp& operator = (sp<U>&& other);
58     template<typename U> sp& operator = (U* other);
59 
60     //! Special optimization for use by ProcessState (and nobody else).
61     void force_set(T* other);
62 
63     // Reset
64 
65     void clear();
66 
67     // Accessors
68 
69     inline T&       operator* () const     { return *m_ptr; }
70     inline T*       operator-> () const    { return m_ptr;  }
get()71     inline T*       get() const            { return m_ptr; }
72     inline explicit operator bool () const { return m_ptr != nullptr; }
73 
74     // Punt these to the wp<> implementation.
75     template<typename U>
76     inline bool operator == (const wp<U>& o) const {
77         return o == *this;
78     }
79 
80     template<typename U>
81     inline bool operator != (const wp<U>& o) const {
82         return o != *this;
83     }
84 
85 private:
86     template<typename Y> friend class sp;
87     template<typename Y> friend class wp;
88     void set_pointer(T* ptr);
89     static inline void check_not_on_stack(const void* ptr);
90     T* m_ptr;
91 };
92 
93 #define COMPARE_STRONG(_op_)                                           \
94     template <typename T, typename U>                                  \
95     static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
96         return t.get() _op_ u.get();                                   \
97     }                                                                  \
98     template <typename T, typename U>                                  \
99     static inline bool operator _op_(const T* t, const sp<U>& u) {     \
100         return t _op_ u.get();                                         \
101     }                                                                  \
102     template <typename T, typename U>                                  \
103     static inline bool operator _op_(const sp<T>& t, const U* u) {     \
104         return t.get() _op_ u;                                         \
105     }                                                                  \
106     template <typename T>                                              \
107     static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
108         return t.get() _op_ nullptr;                                   \
109     }                                                                  \
110     template <typename T>                                              \
111     static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
112         return nullptr _op_ t.get();                                   \
113     }
114 
115 template <template <typename C> class comparator, typename T, typename U>
_sp_compare_(T * a,U * b)116 static inline bool _sp_compare_(T* a, U* b) {
117     return comparator<typename std::common_type<T*, U*>::type>()(a, b);
118 }
119 
120 #define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_)                     \
121     template <typename T, typename U>                                  \
122     static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
123         return _sp_compare_<_compare_>(t.get(), u.get());              \
124     }                                                                  \
125     template <typename T, typename U>                                  \
126     static inline bool operator _op_(const T* t, const sp<U>& u) {     \
127         return _sp_compare_<_compare_>(t, u.get());                    \
128     }                                                                  \
129     template <typename T, typename U>                                  \
130     static inline bool operator _op_(const sp<T>& t, const U* u) {     \
131         return _sp_compare_<_compare_>(t.get(), u);                    \
132     }                                                                  \
133     template <typename T>                                              \
134     static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
135         return _sp_compare_<_compare_>(t.get(), nullptr);              \
136     }                                                                  \
137     template <typename T>                                              \
138     static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
139         return _sp_compare_<_compare_>(nullptr, t.get());              \
140     }
141 
142 COMPARE_STRONG(==)
143 COMPARE_STRONG(!=)
144 COMPARE_STRONG_FUNCTIONAL(>, std::greater)
145 COMPARE_STRONG_FUNCTIONAL(<, std::less)
146 COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
147 COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
148 
149 #undef COMPARE_STRONG
150 #undef COMPARE_STRONG_FUNCTIONAL
151 
152 // For code size reasons, we do not want these inlined or templated.
153 void sp_report_race();
154 void sp_report_stack_pointer();
155 
156 // ---------------------------------------------------------------------------
157 // No user serviceable parts below here.
158 
159 // Check whether address is definitely on the calling stack.  We actually check whether it is on
160 // the same 4K page as the frame pointer.
161 //
162 // Assumptions:
163 // - Pages are never smaller than 4K (MIN_PAGE_SIZE)
164 // - Malloced memory never shares a page with a stack.
165 //
166 // It does not appear safe to broaden this check to include adjacent pages; apparently this code
167 // is used in environments where there may not be a guard page below (at higher addresses than)
168 // the bottom of the stack.
169 template <typename T>
check_not_on_stack(const void * ptr)170 void sp<T>::check_not_on_stack(const void* ptr) {
171     static constexpr int MIN_PAGE_SIZE = 0x1000;  // 4K. Safer than including sys/user.h.
172     static constexpr uintptr_t MIN_PAGE_MASK = ~static_cast<uintptr_t>(MIN_PAGE_SIZE - 1);
173     uintptr_t my_frame_address =
174             reinterpret_cast<uintptr_t>(__builtin_frame_address(0 /* this frame */));
175     if (((reinterpret_cast<uintptr_t>(ptr) ^ my_frame_address) & MIN_PAGE_MASK) == 0) {
176         sp_report_stack_pointer();
177     }
178 }
179 
180 // TODO: Ideally we should find a way to increment the reference count before running the
181 // constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
182 template <typename T>
183 template <typename... Args>
make(Args &&...args)184 sp<T> sp<T>::make(Args&&... args) {
185     T* t = new T(std::forward<Args>(args)...);
186     sp<T> result;
187     result.m_ptr = t;
188     t->incStrong(t);  // bypass check_not_on_stack for heap allocation
189     return result;
190 }
191 
192 template<typename T>
sp(T * other)193 sp<T>::sp(T* other)
194         : m_ptr(other) {
195     if (other) {
196         check_not_on_stack(other);
197         other->incStrong(this);
198     }
199 }
200 
201 template<typename T>
sp(const sp<T> & other)202 sp<T>::sp(const sp<T>& other)
203         : m_ptr(other.m_ptr) {
204     if (m_ptr)
205         m_ptr->incStrong(this);
206 }
207 
208 template <typename T>
sp(sp<T> && other)209 sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
210     other.m_ptr = nullptr;
211 }
212 
213 template<typename T> template<typename U>
sp(U * other)214 sp<T>::sp(U* other)
215         : m_ptr(other) {
216     if (other) {
217         check_not_on_stack(other);
218         (static_cast<T*>(other))->incStrong(this);
219     }
220 }
221 
222 template<typename T> template<typename U>
sp(const sp<U> & other)223 sp<T>::sp(const sp<U>& other)
224         : m_ptr(other.m_ptr) {
225     if (m_ptr)
226         m_ptr->incStrong(this);
227 }
228 
229 template<typename T> template<typename U>
sp(sp<U> && other)230 sp<T>::sp(sp<U>&& other)
231         : m_ptr(other.m_ptr) {
232     other.m_ptr = nullptr;
233 }
234 
235 template<typename T>
~sp()236 sp<T>::~sp() {
237     if (m_ptr)
238         m_ptr->decStrong(this);
239 }
240 
241 template<typename T>
242 sp<T>& sp<T>::operator =(const sp<T>& other) {
243     // Force m_ptr to be read twice, to heuristically check for data races.
244     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
245     T* otherPtr(other.m_ptr);
246     if (otherPtr) otherPtr->incStrong(this);
247     if (oldPtr) oldPtr->decStrong(this);
248     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
249     m_ptr = otherPtr;
250     return *this;
251 }
252 
253 template <typename T>
254 sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
255     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
256     if (oldPtr) oldPtr->decStrong(this);
257     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
258     m_ptr = other.m_ptr;
259     other.m_ptr = nullptr;
260     return *this;
261 }
262 
263 template<typename T>
264 sp<T>& sp<T>::operator =(T* other) {
265     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
266     if (other) {
267         check_not_on_stack(other);
268         other->incStrong(this);
269     }
270     if (oldPtr) oldPtr->decStrong(this);
271     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
272     m_ptr = other;
273     return *this;
274 }
275 
276 template<typename T> template<typename U>
277 sp<T>& sp<T>::operator =(const sp<U>& other) {
278     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
279     T* otherPtr(other.m_ptr);
280     if (otherPtr) otherPtr->incStrong(this);
281     if (oldPtr) oldPtr->decStrong(this);
282     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
283     m_ptr = otherPtr;
284     return *this;
285 }
286 
287 template<typename T> template<typename U>
288 sp<T>& sp<T>::operator =(sp<U>&& other) {
289     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
290     if (m_ptr) m_ptr->decStrong(this);
291     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
292     m_ptr = other.m_ptr;
293     other.m_ptr = nullptr;
294     return *this;
295 }
296 
297 template<typename T> template<typename U>
298 sp<T>& sp<T>::operator =(U* other) {
299     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
300     if (other) (static_cast<T*>(other))->incStrong(this);
301     if (oldPtr) oldPtr->decStrong(this);
302     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
303     m_ptr = other;
304     return *this;
305 }
306 
307 template<typename T>
force_set(T * other)308 void sp<T>::force_set(T* other) {
309     other->forceIncStrong(this);
310     m_ptr = other;
311 }
312 
313 template<typename T>
clear()314 void sp<T>::clear() {
315     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
316     if (oldPtr) {
317         oldPtr->decStrong(this);
318         if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
319         m_ptr = nullptr;
320     }
321 }
322 
323 template<typename T>
set_pointer(T * ptr)324 void sp<T>::set_pointer(T* ptr) {
325     m_ptr = ptr;
326 }
327 
328 }  // namespace android
329 
330 // ---------------------------------------------------------------------------
331 
332 #endif // ANDROID_STRONG_POINTER_H
333