]>
Commit | Line | Data |
---|---|---|
70ad1dc8 A |
1 | /* |
2 | * Copyright (c) 2018 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | /*! | |
25 | * @header | |
26 | * Non-standard, Darwin-specific additions to the stdlib(3) family of APIs. | |
27 | * | |
28 | * The os_malloc() and os_strdup() routines are wrappers to be used for small, | |
29 | * fixed-size allocations, the assumption being that such allocation should | |
30 | * always succeed absent other critical problems. Thus, if the requested size is | |
31 | * is a compile-time constant, the return value is asserted to be non-NULL. | |
32 | * Otherwise, for sizes that are not known at compile-time, the implementations | |
33 | * loop until the allocation succeeds, assuming the failure to be due to | |
34 | * transient resource shortages. The implementation will not loop if the program | |
35 | * has not become multi-threaded, under the assertion that there would be no | |
36 | * point since no other thread could possibly free up resources for the calling | |
37 | * thread to use. Thus, in a single-threaded program, all allocations will | |
38 | * be treated like small, fixed-size allocations and be expected to succeed. | |
39 | * | |
40 | * These wrappers should not be used for large allocations whose bounds cannot | |
41 | * be determined at compile-time. For such allocations, malloc(3), calloc(3), et | |
42 | * al. (with appropriate error handling) are the appropriate interfaces. | |
43 | */ | |
44 | #ifndef __DARWIN_STDLIB_H | |
45 | #define __DARWIN_STDLIB_H | |
46 | ||
47 | #include <os/base.h> | |
48 | #include <os/api.h> | |
49 | #include <os/assumes.h> | |
50 | #include <dispatch/private.h> | |
51 | ||
52 | #include <stdlib.h> | |
53 | #include <sys/types.h> | |
54 | #include <sys/cdefs.h> | |
55 | ||
56 | __BEGIN_DECLS; | |
57 | ||
58 | /*! | |
59 | * @function __os_temporary_resource_shortage | |
60 | * A function whose purpose is to appear in stack traces to indicate transient | |
61 | * resource shortage conditions. Do not call. | |
62 | */ | |
63 | DARWIN_API_AVAILABLE_20170407 | |
64 | OS_EXPORT OS_NOT_TAIL_CALLED | |
65 | void | |
66 | __os_temporary_resource_shortage(void); | |
67 | ||
68 | /*! | |
69 | * @functiongroup | |
70 | * Internal inline definitions. | |
71 | */ | |
72 | DARWIN_API_AVAILABLE_20170407 | |
73 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC __alloc_size(1) | |
74 | static inline void * | |
75 | _os_malloc_loop(size_t size) | |
76 | { | |
77 | void *ptr = NULL; | |
78 | while (!(ptr = malloc(size))) { | |
79 | __os_temporary_resource_shortage(); | |
80 | } | |
81 | return ptr; | |
82 | } | |
83 | ||
84 | DARWIN_API_AVAILABLE_20170407 | |
85 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC __alloc_size(1) | |
86 | static inline void * | |
87 | _os_malloc_known(size_t size) | |
88 | { | |
89 | return malloc(size); | |
90 | } | |
91 | ||
92 | DARWIN_API_AVAILABLE_20170407 | |
93 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC __alloc_size(1, 2) | |
94 | static inline void * | |
95 | _os_calloc_loop(size_t cnt, size_t size) | |
96 | { | |
97 | void *ptr = NULL; | |
98 | while (!(ptr = calloc(cnt, size))) { | |
99 | __os_temporary_resource_shortage(); | |
100 | } | |
101 | return ptr; | |
102 | } | |
103 | ||
104 | DARWIN_API_AVAILABLE_20170407 | |
105 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC __alloc_size(1, 2) | |
106 | static inline void * | |
107 | _os_calloc_known(size_t cnt, size_t size) | |
108 | { | |
109 | return calloc(cnt, size); | |
110 | } | |
111 | ||
112 | DARWIN_API_AVAILABLE_20170407 | |
113 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC | |
114 | static inline char * | |
115 | _os_strdup_loop(const char *str) | |
116 | { | |
117 | char *ptr = NULL; | |
118 | while (!(ptr = strdup(str))) { | |
119 | __os_temporary_resource_shortage(); | |
120 | } | |
121 | return ptr; | |
122 | } | |
123 | ||
124 | DARWIN_API_AVAILABLE_20170407 | |
125 | OS_ALWAYS_INLINE OS_WARN_RESULT OS_MALLOC | |
126 | static inline char * | |
127 | _os_strdup_known(const char *str) | |
128 | { | |
129 | return strdup(str); | |
130 | } | |
131 | ||
132 | /*! | |
133 | * @function os_malloc | |
134 | * Wrapper around malloc(3) which guarantees that the allocation succeeds. | |
135 | * | |
136 | * @param __size | |
137 | * The size of the allocation. | |
138 | * | |
139 | * @result | |
140 | * A new object that the caller is responsible for free(3)ing. | |
141 | * | |
142 | * This routine will never return NULL. If the size of the allocation is known | |
143 | * at compile-time, a failure to allocate the object will abort the caller. If | |
144 | * the size is not known at compile-time, the routine will retry until it is | |
145 | * successful. | |
146 | */ | |
147 | #define os_malloc(__size) ({ \ | |
148 | void *ptr = NULL; \ | |
149 | size_t _size = (__size); \ | |
150 | if (__builtin_constant_p(__size) || !_dispatch_is_multithreaded()) { \ | |
151 | ptr = _os_malloc_known(_size); \ | |
152 | os_assert_malloc("known-constant allocation", ptr, _size); \ | |
153 | } else { \ | |
154 | ptr = _os_malloc_loop(_size); \ | |
155 | } \ | |
156 | (ptr); \ | |
157 | }) | |
158 | ||
159 | /*! | |
160 | * @function os_calloc | |
161 | * Wrapper around calloc(3) which guarantees that the allocation succeeds. | |
162 | * | |
163 | * @param __cnt | |
164 | * The number of elements to allocate. | |
165 | * | |
166 | * @param __size | |
167 | * The size of each element to allocate. | |
168 | * | |
169 | * @result | |
170 | * A new object that the caller is responsible for free(3)ing. | |
171 | * | |
172 | * This routine will never return NULL. If the size of the allocation is known | |
173 | * at compile-time, a failure to allocate the object will abort the caller. If | |
174 | * the size is not known at compile-time, the routine will retry until it is | |
175 | * successful. | |
176 | */ | |
177 | #define os_calloc(__cnt, __size) ({ \ | |
178 | void *ptr = NULL; \ | |
179 | size_t _size = (__size); \ | |
180 | size_t _cnt = (__size); \ | |
181 | if ((__builtin_constant_p(__cnt) && __builtin_constant_p(__size)) || \ | |
182 | !_dispatch_is_multithreaded()) { \ | |
183 | ptr = _os_calloc_known(_cnt, _size); \ | |
184 | os_assert_malloc("known-constant allocation", ptr, _size); \ | |
185 | } else { \ | |
186 | ptr = _os_calloc_loop(_cnt, _size); \ | |
187 | } \ | |
188 | (ptr); \ | |
189 | }) | |
190 | ||
191 | /*! | |
192 | * @function os_strdup | |
193 | * A wrapper around strdup(3) which guarantees that the string duplication | |
194 | * succeeds. | |
195 | * | |
196 | * @param __str | |
197 | * The string to duplicate. | |
198 | * | |
199 | * @result | |
200 | * A new string that the caller is responsible for free(3)ing. | |
201 | * | |
202 | * This routine will never return NULL. If the given string is a compile-time | |
203 | * constant, a failure to duplicate it will abort the caller. If the string is | |
204 | * not a compile-time constant, the routine will retry until it is successful. | |
205 | * | |
206 | * @discussion | |
207 | * strdup(3) is found in the string(3) API family, but this interface is in the | |
208 | * stdlib.h header because its semantic changes are solely related to the manner | |
209 | * in which memory is allocated. | |
210 | */ | |
211 | #define os_strdup(__str) ({ \ | |
212 | char *ptr = NULL; \ | |
213 | const char *_str = (__str); \ | |
214 | if (__builtin_constant_p(__str) || !_dispatch_is_multithreaded()) { \ | |
215 | ptr = _os_strdup_known(_str); \ | |
216 | os_assert_malloc("known-constant allocation", ptr, strlen(_str)); \ | |
217 | } else { \ | |
218 | ptr = _os_strdup_loop(_str); \ | |
219 | } \ | |
220 | (ptr); \ | |
221 | }) | |
222 | ||
223 | /*! | |
224 | * @function os_localtime_file | |
225 | * A routine to generate a time stamp that is suitable for embedding in a file | |
226 | * name. | |
227 | * | |
228 | * @param buff | |
229 | * A pointer to a buffer where the resulting time stamp will be stored. | |
230 | * | |
231 | * @discussion | |
232 | * The resulting time stamp will not include characters which require escaping | |
233 | * in shells, such as spaces. The current implementation format is | |
234 | * | |
235 | * YYYY-MM-DD_HH.MM.SS.us | |
236 | * | |
237 | * e.g. | |
238 | * | |
239 | * 2017-04-24_12.45.15.045609 | |
240 | */ | |
241 | DARWIN_API_AVAILABLE_20170407 | |
242 | OS_EXPORT | |
243 | void | |
244 | os_localtime_file(char buff[32]); | |
245 | ||
246 | /*! | |
247 | * @function os_simple_hash | |
248 | * An implementation of a simple non-cryptographic hashing algorithm. | |
249 | * | |
250 | * @param buff | |
251 | * A pointer to the buffer to hash. | |
252 | * | |
253 | * @param len | |
254 | * The length of the buffer. | |
255 | * | |
256 | * @result | |
257 | * The hashed value of the input. | |
258 | * | |
259 | * @discussion | |
260 | * This routine is meant to be used as a simple way to obtain a value that can | |
261 | * be used to choose a bucket in a simple hash table. Do not attach security | |
262 | * assumptions to the output of this routine. Do not assume thst the computed | |
263 | * hash is stable between hosts, OS versions, or boot sessions. | |
264 | */ | |
265 | DARWIN_API_AVAILABLE_20170407 | |
266 | OS_EXPORT OS_NONNULL1 | |
267 | uint64_t | |
268 | os_simple_hash(const void *buff, size_t len); | |
269 | ||
270 | /*! | |
271 | * @function os_simple_hash_string | |
272 | * An implementation of a simple non-cryptographic hashing algorithm. | |
273 | * | |
274 | * @param string | |
275 | * A pointer to the null-terminated string to hash. | |
276 | * | |
277 | * @result | |
278 | * The hashed value of the input. | |
279 | * | |
280 | * @discussion | |
281 | * This routine is the moral equivalent of a call to | |
282 | * | |
283 | * os_simple_hash(buff, strlen(buff)); | |
284 | * | |
285 | * All the same considerations of {@link os_simple_hash} apply. | |
286 | */ | |
287 | DARWIN_API_AVAILABLE_20170407 | |
288 | OS_EXPORT OS_NONNULL1 | |
289 | uint64_t | |
290 | os_simple_hash_string(const char *string); | |
291 | ||
292 | __END_DECLS; | |
293 | ||
294 | #endif // __DARWIN_STDLIB_H |