1/*
2 * Copyright (c) 2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* IOSymbol.h created by gvdl on Fri 1998-10-30 */
29/* OSSymbol must be created through the factory methods and thus is not subclassable. */
30
31#ifndef _OS_OSSYMBOL_H
32#define _OS_OSSYMBOL_H
33
34#include <kern/smr_types.h>
35#include <libkern/c++/OSString.h>
36#include <libkern/c++/OSPtr.h>
37
38class OSSymbol;
39
40typedef OSSymbol* OSSymbolPtr;
41typedef OSSymbol const* OSSymbolConstPtr;
42
43/*!
44 * @header
45 *
46 * @abstract
47 * This header declares the OSSymbol container class.
48 */
49
50// xx-review: OSSymbol does not override setChar
51
52/*!
53 * @class OSSymbol
54 *
55 * @abstract
56 * OSSymbol wraps a C string in a unique C++ object
57 * for use as keys in Libkern collections.
58 *
59 * @discussion
60 * OSSymbol is a container class for managing uniqued strings,
61 * for example, those used as dictionary keys.
62 * Its static instance-creation functions check
63 * for an existing instance of OSSymbol
64 * with the requested C string value before creating a new object.
65 * If an instance already exists in the pool of unique symbols,
66 * its reference count is incremented
67 * and the existing instance is returned.
68 *
69 * While OSSymbol provides for uniquing of a given string value,
70 * it makes no effort to enforce immutability of that value.
71 * Altering the contents of an OSSymbol should be avoided.
72 *
73 * <b>Use Restrictions</b>
74 *
75 * With very few exceptions in the I/O Kit, all Libkern-based C++
76 * classes, functions, and macros are <b>unsafe</b>
77 * to use in a primary interrupt context.
78 * Consult the I/O Kit documentation related to primary interrupts
79 * for more information.
80 *
81 * OSSymbol provides no concurrency protection;
82 * it's up to the usage context to provide any protection necessary.
83 * Some portions of the I/O Kit, such as
84 * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link,
85 * handle synchronization via defined member functions for setting
86 * properties.
87 */
88class OSSymbol final : public OSString
89{
90 friend class OSSymbolPool;
91
92 OSDeclareDefaultStructors(OSSymbol);
93
94private:
95 struct smrq_slink hashlink;
96
97 static void initialize();
98
99/*!
100 * @function initWithString
101 *
102 * @abstract
103 * Overridden to prevent creation of duplicate symbols.
104 *
105 * @param aString Unused.
106 *
107 * @result
108 * <code>false</code>.
109 *
110 * @discussion
111 * Overrides OSString's implementation to prevent creation
112 * of distinct OSSymbols with the same string value.
113 */
114 virtual bool initWithString(const OSString * aString) APPLE_KEXT_OVERRIDE;
115
116
117/*!
118 * @function initWithCString
119 *
120 * @abstract
121 * Overridden to prevent creation of duplicate symbols.
122 *
123 * @param cString Unused.
124 *
125 * @result
126 * <code>false</code>.
127 *
128 * @discussion
129 * Overrides OSString's implementation to prevent creation
130 * of distinct OSSymbols with the same string value.
131 */
132 virtual bool initWithCString(const char * cString) APPLE_KEXT_OVERRIDE;
133
134
135/*!
136 * @function initWithCStringNoCopy
137 *
138 * @abstract
139 * Overridden to prevent creation of duplicate symbols.
140 *
141 * @param cString Unused.
142 *
143 * @result
144 * <code>false</code>.
145 *
146 * @discussion
147 * Overrides OSString's implementation to prevent creation
148 * of distinct OSSymbols with the same string value.
149 */
150 virtual bool initWithCStringNoCopy(const char *cString) APPLE_KEXT_OVERRIDE;
151
152protected:
153
154/*!
155 * @function taggedRetain
156 *
157 * @abstract
158 * Overrides
159 * <code>@link
160 * //apple_ref/cpp/instm/OSObject/taggedRetain/virtualvoid/(constvoid*)
161 * OSObject::taggedRetain(const void *) const@/link</code>
162 * to synchronize with the symbol pool.
163 *
164 * @param tag Used for tracking collection references.
165 */
166 virtual void taggedRetain(
167 const void * tag) const APPLE_KEXT_OVERRIDE;
168
169/*!
170 * @function taggedRelease
171 *
172 * @abstract
173 * Overrides
174 * <code>@link
175 * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*,constint)
176 * OSObject::taggedRelease(const void *, const int)@/link</code>
177 * to synchronize with the symbol pool.
178 *
179 * @param tag Used for tracking collection references.
180 * @param freeWhen If decrementing the reference count makes it
181 * >= <code>freeWhen</code>, the object is immediately freed.
182 *
183 * @discussion
184 * Because OSSymbol shares instances, the reference-counting functions
185 * must synchronize access to the class-internal tables
186 * used to track those instances.
187 */
188 virtual void taggedRelease(
189 const void * tag,
190 const int freeWhen) const APPLE_KEXT_OVERRIDE;
191
192
193// xx-review: should we just omit this from headerdoc?
194/*!
195 * @function free
196 *
197 * @abstract
198 * Overrides
199 * <code>@link
200 * //apple_ref/cpp/instm/OSObject/free/virtualvoid/()
201 * OSObject::free@/link</code>
202 * to synchronize with the symbol pool.
203 *
204 * @discussion
205 * Because OSSymbol shares instances, the reference-counting functions
206 * must synchronize access to the class-internal tables
207 * used to track those instances.
208 */
209 virtual void free() APPLE_KEXT_OVERRIDE;
210
211public:
212
213// xx-review: should we just omit this from headerdoc?
214/*!
215 * @function taggedRelease
216 *
217 * @abstract
218 * Overrides
219 * <code>@link
220 * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*)
221 * OSObject::taggedRelease(const void *)@/link</code>
222 * to synchronize with the symbol pool.
223 *
224 * @param tag Used for tracking collection references.
225 *
226 * @discussion
227 * Because OSSymbol shares instances, the reference-counting functions
228 * must synchronize access to the class-internal tables
229 * used to track those instances.
230 */
231
232/* Original note (not for headerdoc):
233 * The C++ language has forced me to override this method
234 * even though I have implemented it as
235 * <code>{ super::taggedRelease(tag) }</code>.
236 * It seems that C++ is confused about the appearance of the protected
237 * taggedRelease with 2 parameters and refuses to only inherit one function.
238 * See
239 * <code>@link
240 * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*,constint)
241 * OSObject::taggedRelease(const void *, const int)@/link</code>.
242 */
243 virtual void taggedRelease(const void * tag) const APPLE_KEXT_OVERRIDE;
244
245
246/*!
247 * @function withString
248 *
249 * @abstract
250 * Returns an OSSymbol created from an OSString,
251 * or the existing unique instance of the same value.
252 *
253 * @param aString The OSString object to look up or copy.
254 *
255 * @result
256 * An instance of OSSymbol
257 * representing the same characters as <code>aString</code>;
258 * <code>NULL</code> on failure.
259 *
260 * @discussion
261 * This function creates or returns the unique OSSymbol instance
262 * representing the string value of <code>aString</code>.
263 * You can compare it with other OSSymbols using the <code>==</code> operator.
264 *
265 * OSSymbols are reference-counted normally.
266 * This function either returns a
267 * new OSSymbol with a retain count of 1,
268 * or increments the retain count of the existing instance.
269 */
270 static OSPtr<const OSSymbol> withString(const OSString * aString);
271
272
273/*!
274 * @function withCString
275 *
276 * @abstract
277 * Returns an OSSymbol created from a C string,
278 * or the existing unique instance of the same value.
279 *
280 * @param cString The C string to look up or copy.
281 *
282 * @result
283 * An instance of OSSymbol representing
284 * the same characters as <code>cString</code>;
285 * <code>NULL</code> on failure.
286 *
287 * @discussion
288 * This function returns the unique OSSymbol instance
289 * representing the string value of <code>cString</code>.
290 * You can compare it with other OSSymbols using the <code>==</code> operator.
291 *
292 * OSSymbols are reference-counted normally.
293 * This function either returns a
294 * new OSSymbol with a retain count of 1,
295 * or increments the retain count of the existing instance.
296 */
297 static OSPtr<const OSSymbol> withCString(const char * cString);
298
299
300/*!
301 * @function withCStringNoCopy
302 *
303 * @abstract
304 * Returns an OSSymbol created from a C string,
305 * without copying that string,
306 * or the existing unique instance of the same value.
307 *
308 * @param cString The C string to look up or use.
309 * @result
310 * An instance of OSSymbol representing
311 * the same characters as <code>cString</code>;
312 * <code>NULL</code>.
313 *
314 * @discussion
315 * Avoid using this function;
316 * OSSymbols should own their internal string buffers.
317 *
318 * This function returns the unique OSSymbol instance
319 * representing the string value of <code>cString</code>.
320 * You can compare it with other OSSymbols using the <code>==</code> operator.
321 *
322 * OSSymbols are reference-counted normally.
323 * This function either returns a
324 * new OSSymbol with a retain count of 1,
325 * or increments the retain count of the existing instance.
326 */
327 static OSPtr<const OSSymbol> withCStringNoCopy(const char * cString);
328
329/*!
330 * @function existingSymbolForString
331 *
332 * @abstract
333 * Returns an existing OSSymbol for the given OSString.
334 *
335 * @param aString The OSString Object to look up.
336 *
337 * @result
338 * An existing instance of OSSymbol representing
339 * the same characters as <code>aString</code>;
340 * <code>NULL</code> if none is found.
341 *
342 * @discussion
343 * The returned OSSymbol object is returned with an incremented refcount
344 * that needs to be released.
345 */
346 static OSPtr<const OSSymbol> existingSymbolForString(const OSString *aString);
347
348/*!
349 * @function existingSymbolForCString
350 *
351 * @abstract
352 * Returns an existing OSSymbol for the given C string.
353 *
354 * @param aCString The C string to look up.
355 *
356 * @result
357 * An existing instance of OSSymbol representing
358 * the same characters as <code>aString</code>;
359 * <code>NULL</code> if none is found.
360 *
361 * @discussion
362 * The returned OSSymbol object is returned with an incremented refcount
363 * that needs to be released.
364 */
365 static OSPtr<const OSSymbol> existingSymbolForCString(const char *aCString);
366
367/*!
368 * @function isEqualTo
369 *
370 * @abstract
371 * Tests the equality of two OSSymbol objects.
372 *
373 * @param aSymbol The OSSymbol object being compared against the receiver.
374 *
375 * @result
376 * <code>true</code> if the two OSSymbol objects are equivalent,
377 * <code>false</code> otherwise.
378 *
379 * @discussion
380 * Two OSSymbol objects are considered equal if they have the same address;
381 * that is, this function is equivalent to the <code>==</code> operator.
382 */
383 virtual bool isEqualTo(const OSSymbol * aSymbol) const;
384
385
386/*!
387 * @function isEqualTo
388 *
389 * @abstract Tests the equality of an OSSymbol object with a C string.
390 *
391 * @param cString The C string to compare against the receiver.
392 *
393 * @result
394 * <code>true</code> if the OSSymbol's characters
395 * are equivalent to the C string's,
396 * <code>false</code> otherwise.
397 */
398 virtual bool isEqualTo(const char * cString) const APPLE_KEXT_OVERRIDE;
399
400
401/*!
402 * @function isEqualTo
403 *
404 * @abstract Tests the equality of an OSSymbol object to an arbitrary object.
405 *
406 * @param anObject The object to be compared against the receiver.
407 * @result Returns <code>true</code> if the two objects are equivalent,
408 * <code>false</code> otherwise.
409 *
410 * @discussion
411 * An OSSymbol is considered equal to another object
412 * if that object is derived from
413 * @link //apple_ref/doc/class/OSMetaClassBase OSString@/link
414 * and contains the equivalent bytes of the same length.
415 */
416 virtual bool isEqualTo(const OSMetaClassBase * anObject) const APPLE_KEXT_OVERRIDE;
417
418
419#ifdef XNU_KERNEL_PRIVATE
420/* OSRuntime only INTERNAL API - DO NOT USE */
421/* Not to be included in headerdoc. */
422// xx-review: this should be removed from the symbol set.
423
424 static void checkForPageUnload(
425 void * startAddr,
426 void * endAddr);
427
428 static unsigned int bsearch(
429 const void * key,
430 const void * array,
431 unsigned int arrayCount,
432 size_t memberSize);
433
434 inline void smr_free();
435
436 inline uint32_t hash() const;
437
438#endif /* XNU_KERNEL_PRIVATE */
439
440 OSMetaClassDeclareReservedUnused(OSSymbol, 0);
441 OSMetaClassDeclareReservedUnused(OSSymbol, 1);
442 OSMetaClassDeclareReservedUnused(OSSymbol, 2);
443 OSMetaClassDeclareReservedUnused(OSSymbol, 3);
444 OSMetaClassDeclareReservedUnused(OSSymbol, 4);
445 OSMetaClassDeclareReservedUnused(OSSymbol, 5);
446 OSMetaClassDeclareReservedUnused(OSSymbol, 6);
447 OSMetaClassDeclareReservedUnused(OSSymbol, 7);
448};
449
450#endif /* !_OS_OSSYMBOL_H */
451