]>
git.saurik.com Git - apple/libc.git/blob - libdarwin/h/cleanup.h
2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 * Attributes to handle automatic clean-up of certain types of variables when
27 * they go out of scope.
29 * IMPORTANT: These attributes will NOT cause a variable to be cleaned up when
30 * its value changes. For example, this pattern would leak:
32 * void *__os_free ptr = malloc(10);
33 * ptr = somewhere_else;
36 * You should only use these attributes for very well-scoped, temporary
39 #ifndef __DARWIN_CLEANUP_H
40 #define __DARWIN_CLEANUP_H
44 #include <os/assumes.h>
45 #include <os/object_private.h>
48 #include <sys/errno.h>
49 #include <sys/cdefs.h>
54 #include <mach/mach_init.h>
55 #include <mach/port.h>
56 #include <mach/mach_port.h>
57 #include <mach/kern_return.h>
58 #include <mach/mach_right.h>
62 #if __has_attribute(cleanup)
65 * An attribute that may be applied to a variable's type. This attribute causes
66 * the variable to be passed to free(3) when it goes out of scope. Applying this
67 * attribute to variables that do not reference heap allocations will result in
70 #define __os_free __attribute__((cleanup(__os_cleanup_free)))
72 __os_cleanup_free(void *__p
)
74 void **tp
= (void **)__p
;
81 * An attribute that may be applied to a variable's type. This attribute causes
82 * the variable to be passed to close(2) when it goes out of scope. Applying
83 * this attribute to variables that do not reference a valid file descriptor
84 * will result in undefined behavior. If the variable's value is -1 upon going
85 * out-of-scope, no cleanup is performed.
87 #define __os_close __attribute__((cleanup(__os_cleanup_close)))
89 __os_cleanup_close(int *__fd
)
95 posix_assert_zero(close(fd
));
100 * An attribute that may be applied to a variable's type. This attribute causes
101 * the variable to be passed to fclose(3) when it goes out of scope. Applying
102 * this attribute to variables that do not reference a valid FILE* will result
103 * in undefined behavior. If the variable's value is NULL upon going out-of-
104 * scope, no cleanup is performed.
106 #define __os_fclose __attribute__((cleanup(__os_cleanup_fclose)))
108 __os_cleanup_fclose(FILE **__fp
)
119 os_assert_zero(errno
);
124 * @define __os_close_mach_recv
125 * An attribute that may be applied to a variable's type. This attribute causes
126 * the variable to be wrapped in a mach receive right object and passed to
127 * {@link mach_right_recv_destruct} when it goes out of scope. Applying this
128 * attribute to variables that do not reference a valid Mach port receive right
129 * will result in undefined behavior. If the variable's value is MACH_PORT_NULL
130 * or MACH_PORT_DEAD upon going out-of-scope, no cleanup is performed.
132 #define __os_close_mach_recv \
133 __attribute__((cleanup(__os_cleanup_close_mach_recv)))
135 __os_cleanup_close_mach_recv(mach_port_t
*__p
)
137 mach_port_t p
= *__p
;
138 mach_right_recv_t mr
= mach_right_recv(p
);
140 if (!MACH_PORT_VALID(p
)) {
144 mach_right_recv_destruct(mr
, NULL
, 0);
148 * @define __os_release_mach_send
149 * An attribute that may be applied to a variable's type. This attribute causes
150 * the variable to be wrapped in a mach send right object and passed to
151 * {@link mach_right_send_release} when it goes out of scope. Applying this
152 * attribute to variables that do not reference a valid Mach port send right or
153 * MACH_PORT_NULL or MACH_PORT_DEAD will result in undefined behavior. If the
154 * variable's value is MACH_PORT_NULL or MACH_PORT_DEAD upon going out-of-scope,
155 * no cleanup is performed.
157 #define __os_release_mach_send \
158 __attribute__((cleanup(__os_cleanup_release_mach_send)))
160 __os_cleanup_release_mach_send(mach_port_t
*__p
)
162 mach_port_t p
= *__p
;
163 mach_right_send_t ms
= mach_right_send(p
);
165 if (!MACH_PORT_VALID(p
)) {
169 mach_right_send_release(ms
);
173 * @define __os_preserve_errno
174 * An attribute that may be applied to a variable's type. This attribute sets
175 * the global errno to the value of the variable when the variable goes out of
176 * scope. This attribute is useful for preserving the value of errno upon entry
177 * to a function and guaranteeing that it is restored upon exit.
179 #define __os_preserve_errno \
180 __unused __attribute__((cleanup(__os_cleanup_errno)))
182 __os_cleanup_errno(int *__e
)
188 * @define __os_release
189 * An attribute that may be applied to a variable's type. This attribute causes
190 * the variable to be passed to os_release() when it goes out of scope. Applying
191 * this attribute to a variable which does not reference a valid os_object_t
192 * object will result in undefined behavior. If the variable's value is NULL
193 * upon going out-of-scope, no cleanup is performed.
195 * This attribute may be applied to dispatch and XPC objects.
197 * When compiling with ARC, this attribute does nothing.
199 #if __has_feature(objc_arc)
202 #define __os_release __attribute__((cleanup(__os_cleanup_os_release)))
204 __os_cleanup_os_release(void *__p
)
206 _os_object_t
*tp
= (_os_object_t
*)__p
;
207 _os_object_t o
= *tp
;
215 #if __COREFOUNDATION__
217 * @define __os_cfrelease
218 * An attribute that may be applied to a variable's type. This attribute causes
219 * the variable to be passed to CFRelease() when it goes out of scope. Applying
220 * this attribute to a variable which does not reference a valid CoreFoundation
221 * object will result in undefined behavior. If the variable's value is NULL
222 * upon going out-of-scope, no cleanup is performed.
224 #define __os_cfrelease __attribute__((cleanup(__os_cleanup_cfrelease)))
226 __os_cleanup_cfrelease(void *__p
)
228 CFTypeRef
*tp
= (CFTypeRef
*)__p
;
235 #endif // __COREFOUNDATION__
238 * @define __os_unfair_unlock
239 * An attribute that may be applied to a variable's type. This attribute causes
240 * the variable to be passed to os_unfair_lock_unlock() when it goes out of
241 * scope. Applying this attribute to a variable which does not reference a valid
242 * os_unfair_lock_t object will result in undefined behavior. If the variable's
243 * value is NULL upon going out-of-scope, no cleanup is performed.
245 * This attribute is useful even when the target lock is taken conditionally via
246 * the following pattern:
248 * os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
249 * os_unfair_lock_t __os_unfair_unlock l2un = NULL;
251 * if (take_the_lock) {
252 * os_unfair_lock_lock(&lock);
254 * // Guarantee that 'lock' will be unconditionally released when the
255 * // scope containing 'l2un' ends.
259 #define __os_unfair_unlock __attribute__((cleanup(__os_cleanup_unfair_unlock)))
261 __os_cleanup_unfair_unlock(void *__p
)
263 os_unfair_lock_t
*tp
= (os_unfair_lock_t
*)__p
;
264 os_unfair_lock_t ufl
= *tp
;
268 os_unfair_lock_assert_owner(ufl
);
269 os_unfair_lock_unlock(ufl
);
272 #else // __has_attribute(cleanup)
273 #define __os_cleanup_unsupported \
274 _Pragma("GCC error \"automatic cleanup not supported\"")
275 #define __os_free __os_cleanup_unsupported
276 #define __os_close __os_cleanup_unsupported
277 #define __os_fclose __os_cleanup_unsupported
278 #define __os_close_mach_recv __os_cleanup_unsupported
279 #define __os_release_mach_send __os_cleanup_unsupported
280 #define __os_preserve_errno __os_cleanup_unsupported
281 #define __os_release __os_cleanup_unsupported
282 #define __os_cfrelease __os_cleanup_unsupported
283 #define __os_unfair_unlock __os_cleanup_unsupported
284 #endif // __has_attribute(cleanup)
288 #endif // __DARWIN_CLEANUP_H