]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSSymbol.cpp
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / libkern / c++ / OSSymbol.cpp
CommitLineData
1c79356b 1/*
39037602 2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* IOSymbol.cpp created by gvdl on Fri 1998-11-17 */
29
f427ee49
A
30#define IOKIT_ENABLE_SHARED_PTR
31
9bccf70c 32#include <string.h>
1c79356b
A
33#include <sys/cdefs.h>
34
fe8ab488 35#include <kern/locks.h>
1c79356b
A
36
37#include <libkern/c++/OSSymbol.h>
f427ee49 38#include <libkern/c++/OSSharedPtr.h>
1c79356b 39#include <libkern/c++/OSLib.h>
f427ee49 40#include <os/cpp_util.h>
9bccf70c 41#include <string.h>
1c79356b
A
42
43#define super OSString
44
39236c6e 45typedef struct { unsigned int i, j; } OSSymbolPoolState;
1c79356b 46
f427ee49 47#define INITIAL_POOL_SIZE ((unsigned int)((exp2ml(1 + log2(kInitBucketCount)))))
2d21ac55
A
48
49#define GROW_FACTOR (1)
50#define SHRINK_FACTOR (3)
51
52#define GROW_POOL() do \
53 if (count * GROW_FACTOR > nBuckets) { \
0a7de745 54 reconstructSymbols(true); \
2d21ac55
A
55 } \
56while (0)
57
58#define SHRINK_POOL() do \
59 if (count * SHRINK_FACTOR < nBuckets && \
0a7de745
A
60 nBuckets > INITIAL_POOL_SIZE) { \
61 reconstructSymbols(false); \
2d21ac55
A
62 } \
63while (0)
64
1c79356b
A
65class OSSymbolPool
66{
67private:
0a7de745
A
68 static const unsigned int kInitBucketCount = 16;
69
70 typedef struct { unsigned int count; OSSymbol **symbolP; } Bucket;
71
72 Bucket *buckets;
73 unsigned int nBuckets;
74 unsigned int count;
75 lck_rw_t *poolGate;
76
77 static inline void
78 hashSymbol(const char *s,
79 unsigned int *hashP,
80 unsigned int *lenP)
81 {
82 unsigned int hash = 0;
83 unsigned int len = 0;
84
85 /* Unroll the loop. */
86 for (;;) {
87 if (!*s) {
88 break;
89 }
f427ee49 90 len++; hash ^= (unsigned int)(unsigned char) *s++;
0a7de745
A
91 if (!*s) {
92 break;
93 }
f427ee49 94 len++; hash ^= ((unsigned int)(unsigned char) *s++) << 8;
0a7de745
A
95 if (!*s) {
96 break;
97 }
f427ee49 98 len++; hash ^= ((unsigned int)(unsigned char) *s++) << 16;
0a7de745
A
99 if (!*s) {
100 break;
101 }
f427ee49 102 len++; hash ^= ((unsigned int)(unsigned char) *s++) << 24;
0a7de745
A
103 }
104 *lenP = len;
105 *hashP = hash;
106 }
107
108 static unsigned long log2(unsigned int x);
f427ee49 109 static unsigned long exp2ml(unsigned long x);
0a7de745
A
110
111 void reconstructSymbols(void);
112 void reconstructSymbols(bool grow);
1c79356b
A
113
114public:
0a7de745
A
115 static void *operator new(size_t size);
116 static void operator delete(void *mem, size_t size);
1c79356b 117
0a7de745
A
118 OSSymbolPool()
119 {
120 }
121 OSSymbolPool(const OSSymbolPool *old);
122 virtual
123 ~OSSymbolPool();
1c79356b 124
0a7de745 125 bool init();
1c79356b 126
0a7de745
A
127 inline void
128 closeReadGate()
129 {
130 lck_rw_lock(poolGate, LCK_RW_TYPE_SHARED);
131 }
132
133 inline void
134 openReadGate()
135 {
136 lck_rw_unlock(poolGate, LCK_RW_TYPE_SHARED);
137 }
138
139
140 inline void
141 closeWriteGate()
142 {
143 lck_rw_lock(poolGate, LCK_RW_TYPE_EXCLUSIVE);
144 }
145
146 inline void
147 openWriteGate()
148 {
149 lck_rw_unlock(poolGate, LCK_RW_TYPE_EXCLUSIVE);
150 }
1c79356b 151
f427ee49
A
152 OSSharedPtr<OSSymbol> findSymbol(const char *cString) const;
153 OSSharedPtr<OSSymbol> insertSymbol(OSSymbol *sym);
0a7de745 154 void removeSymbol(OSSymbol *sym);
1c79356b 155
0a7de745 156 OSSymbolPoolState initHashState();
f427ee49 157 LIBKERN_RETURNS_NOT_RETAINED OSSymbol * nextHashState(OSSymbolPoolState *stateP);
1c79356b
A
158};
159
0a7de745
A
160void *
161OSSymbolPool::operator new(size_t size)
1c79356b 162{
0a7de745
A
163 void *mem = (void *)kalloc_tag(size, VM_KERN_MEMORY_LIBKERN);
164 OSMETA_ACCUMSIZE(size);
165 assert(mem);
166 bzero(mem, size);
1c79356b 167
0a7de745 168 return mem;
1c79356b
A
169}
170
0a7de745
A
171void
172OSSymbolPool::operator delete(void *mem, size_t size)
1c79356b 173{
0a7de745
A
174 kfree(mem, size);
175 OSMETA_ACCUMSIZE(-size);
1c79356b
A
176}
177
b0d623f7
A
178extern lck_grp_t *IOLockGroup;
179
0a7de745
A
180bool
181OSSymbolPool::init()
1c79356b 182{
0a7de745
A
183 count = 0;
184 nBuckets = INITIAL_POOL_SIZE;
185 buckets = (Bucket *) kalloc_tag(nBuckets * sizeof(Bucket), VM_KERN_MEMORY_LIBKERN);
186 OSMETA_ACCUMSIZE(nBuckets * sizeof(Bucket));
187 if (!buckets) {
188 return false;
189 }
0a7de745 190 bzero(buckets, nBuckets * sizeof(Bucket));
1c79356b 191
0a7de745 192 poolGate = lck_rw_alloc_init(IOLockGroup, LCK_ATTR_NULL);
1c79356b 193
cb323159 194 return poolGate != NULL;
1c79356b
A
195}
196
197OSSymbolPool::OSSymbolPool(const OSSymbolPool *old)
198{
0a7de745
A
199 count = old->count;
200 nBuckets = old->nBuckets;
201 buckets = old->buckets;
1c79356b 202
cb323159 203 poolGate = NULL; // Do not duplicate the poolGate
1c79356b
A
204}
205
206OSSymbolPool::~OSSymbolPool()
207{
0a7de745
A
208 if (buckets) {
209 Bucket *thisBucket;
210 for (thisBucket = &buckets[0]; thisBucket < &buckets[nBuckets]; thisBucket++) {
211 if (thisBucket->count > 1) {
212 kfree(thisBucket->symbolP, thisBucket->count * sizeof(OSSymbol *));
213 OSMETA_ACCUMSIZE(-(thisBucket->count * sizeof(OSSymbol *)));
214 }
215 }
216 kfree(buckets, nBuckets * sizeof(Bucket));
217 OSMETA_ACCUMSIZE(-(nBuckets * sizeof(Bucket)));
218 }
219
220 if (poolGate) {
221 lck_rw_free(poolGate, IOLockGroup);
222 }
1c79356b
A
223}
224
0a7de745
A
225unsigned long
226OSSymbolPool::log2(unsigned int x)
1c79356b 227{
0a7de745 228 unsigned long i;
1c79356b 229
0a7de745
A
230 for (i = 0; x > 1; i++) {
231 x >>= 1;
232 }
233 return i;
1c79356b
A
234}
235
0a7de745 236unsigned long
f427ee49 237OSSymbolPool::exp2ml(unsigned long x)
1c79356b 238{
0a7de745 239 return (1 << x) - 1;
1c79356b
A
240}
241
0a7de745
A
242OSSymbolPoolState
243OSSymbolPool::initHashState()
1c79356b 244{
0a7de745
A
245 OSSymbolPoolState newState = { nBuckets, 0 };
246 return newState;
1c79356b
A
247}
248
0a7de745
A
249OSSymbol *
250OSSymbolPool::nextHashState(OSSymbolPoolState *stateP)
1c79356b 251{
0a7de745
A
252 Bucket *thisBucket = &buckets[stateP->i];
253
254 while (!stateP->j) {
255 if (!stateP->i) {
cb323159 256 return NULL;
0a7de745
A
257 }
258 stateP->i--;
259 thisBucket--;
260 stateP->j = thisBucket->count;
261 }
1c79356b 262
0a7de745
A
263 stateP->j--;
264 if (thisBucket->count == 1) {
265 return (OSSymbol *) thisBucket->symbolP;
266 } else {
267 return thisBucket->symbolP[stateP->j];
268 }
1c79356b
A
269}
270
0a7de745
A
271void
272OSSymbolPool::reconstructSymbols(void)
1c79356b 273{
0a7de745 274 this->reconstructSymbols(true);
2d21ac55
A
275}
276
0a7de745
A
277void
278OSSymbolPool::reconstructSymbols(bool grow)
279{
280 unsigned int new_nBuckets = nBuckets;
281 OSSymbol *insert;
282 OSSymbolPoolState state;
283
284 if (grow) {
285 new_nBuckets += new_nBuckets + 1;
286 } else {
287 /* Don't shrink the pool below the default initial size.
288 */
289 if (nBuckets <= INITIAL_POOL_SIZE) {
290 return;
291 }
292 new_nBuckets = (new_nBuckets - 1) / 2;
293 }
294
295 /* Create old pool to iterate after doing above check, cause it
296 * gets finalized at return.
297 */
298 OSSymbolPool old(this);
299
300 count = 0;
301 nBuckets = new_nBuckets;
302 buckets = (Bucket *) kalloc_tag(nBuckets * sizeof(Bucket), VM_KERN_MEMORY_LIBKERN);
303 OSMETA_ACCUMSIZE(nBuckets * sizeof(Bucket));
304 /* @@@ gvdl: Zero test and panic if can't set up pool */
305 bzero(buckets, nBuckets * sizeof(Bucket));
306
307 state = old.initHashState();
308 while ((insert = old.nextHashState(&state))) {
309 insertSymbol(insert);
310 }
1c79356b
A
311}
312
f427ee49 313OSSharedPtr<OSSymbol>
0a7de745 314OSSymbolPool::findSymbol(const char *cString) const
1c79356b 315{
0a7de745
A
316 Bucket *thisBucket;
317 unsigned int j, inLen, hash;
318 OSSymbol *probeSymbol, **list;
f427ee49 319 OSSharedPtr<OSSymbol> ret;
1c79356b 320
0a7de745
A
321 hashSymbol(cString, &hash, &inLen); inLen++;
322 thisBucket = &buckets[hash % nBuckets];
323 j = thisBucket->count;
1c79356b 324
0a7de745 325 if (!j) {
cb323159 326 return NULL;
0a7de745 327 }
1c79356b 328
0a7de745
A
329 if (j == 1) {
330 probeSymbol = (OSSymbol *) thisBucket->symbolP;
1c79356b 331
0a7de745
A
332 if (inLen == probeSymbol->length
333 && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0
334 && probeSymbol->taggedTryRetain(nullptr)) {
f427ee49
A
335 ret.reset(probeSymbol, OSNoRetain);
336 return ret;
0a7de745 337 }
cb323159 338 return NULL;
0a7de745 339 }
1c79356b 340
0a7de745
A
341 for (list = thisBucket->symbolP; j--; list++) {
342 probeSymbol = *list;
343 if (inLen == probeSymbol->length
344 && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0
345 && probeSymbol->taggedTryRetain(nullptr)) {
f427ee49
A
346 ret.reset(probeSymbol, OSNoRetain);
347 return ret;
0a7de745
A
348 }
349 }
1c79356b 350
cb323159 351 return NULL;
1c79356b
A
352}
353
f427ee49 354OSSharedPtr<OSSymbol>
0a7de745
A
355OSSymbolPool::insertSymbol(OSSymbol *sym)
356{
357 const char *cString = sym->string;
358 Bucket *thisBucket;
359 unsigned int j, inLen, hash;
360 OSSymbol *probeSymbol, **list;
f427ee49 361 OSSharedPtr<OSSymbol> ret;
0a7de745
A
362
363 hashSymbol(cString, &hash, &inLen); inLen++;
364 thisBucket = &buckets[hash % nBuckets];
365 j = thisBucket->count;
366
367 if (!j) {
368 thisBucket->symbolP = (OSSymbol **) sym;
369 thisBucket->count++;
370 count++;
371 return nullptr;
372 }
373
374 if (j == 1) {
375 probeSymbol = (OSSymbol *) thisBucket->symbolP;
376
377 if (inLen == probeSymbol->length
378 && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0
379 && probeSymbol->taggedTryRetain(nullptr)) {
f427ee49
A
380 ret.reset(probeSymbol, OSNoRetain);
381 return ret;
0a7de745
A
382 }
383
384 list = (OSSymbol **) kalloc_tag(2 * sizeof(OSSymbol *), VM_KERN_MEMORY_LIBKERN);
385 OSMETA_ACCUMSIZE(2 * sizeof(OSSymbol *));
386 /* @@@ gvdl: Zero test and panic if can't set up pool */
387 list[0] = sym;
388 list[1] = probeSymbol;
389 thisBucket->symbolP = list;
390 thisBucket->count++;
391 count++;
392 GROW_POOL();
393
394 return nullptr;
395 }
396
397 for (list = thisBucket->symbolP; j--; list++) {
398 probeSymbol = *list;
399 if (inLen == probeSymbol->length
400 && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0
401 && probeSymbol->taggedTryRetain(nullptr)) {
f427ee49
A
402 ret.reset(probeSymbol, OSNoRetain);
403 return ret;
0a7de745
A
404 }
405 }
406
407 j = thisBucket->count++;
408 count++;
409 list = (OSSymbol **) kalloc_tag(thisBucket->count * sizeof(OSSymbol *), VM_KERN_MEMORY_LIBKERN);
410 OSMETA_ACCUMSIZE(thisBucket->count * sizeof(OSSymbol *));
411 /* @@@ gvdl: Zero test and panic if can't set up pool */
412 list[0] = sym;
413 bcopy(thisBucket->symbolP, list + 1, j * sizeof(OSSymbol *));
414 kfree(thisBucket->symbolP, j * sizeof(OSSymbol *));
415 OSMETA_ACCUMSIZE(-(j * sizeof(OSSymbol *)));
416 thisBucket->symbolP = list;
417 GROW_POOL();
418
419 return nullptr;
1c79356b
A
420}
421
0a7de745
A
422void
423OSSymbolPool::removeSymbol(OSSymbol *sym)
1c79356b 424{
0a7de745
A
425 Bucket *thisBucket;
426 unsigned int j, inLen, hash;
427 OSSymbol *probeSymbol, **list;
428
429 hashSymbol(sym->string, &hash, &inLen); inLen++;
430 thisBucket = &buckets[hash % nBuckets];
431 j = thisBucket->count;
432 list = thisBucket->symbolP;
433
434 if (!j) {
435 // couldn't find the symbol; probably means string hash changed
436 panic("removeSymbol %s count %d ", sym->string ? sym->string : "no string", count);
437 return;
438 }
1c79356b 439
0a7de745
A
440 if (j == 1) {
441 probeSymbol = (OSSymbol *) list;
442
443 if (probeSymbol == sym) {
cb323159 444 thisBucket->symbolP = NULL;
0a7de745
A
445 count--;
446 thisBucket->count--;
447 SHRINK_POOL();
448 return;
449 }
450 // couldn't find the symbol; probably means string hash changed
451 panic("removeSymbol %s count %d ", sym->string ? sym->string : "no string", count);
452 return;
453 }
1c79356b 454
0a7de745
A
455 if (j == 2) {
456 probeSymbol = list[0];
457 if (probeSymbol == sym) {
458 thisBucket->symbolP = (OSSymbol **) list[1];
459 kfree(list, 2 * sizeof(OSSymbol *));
460 OSMETA_ACCUMSIZE(-(2 * sizeof(OSSymbol *)));
461 count--;
462 thisBucket->count--;
463 SHRINK_POOL();
464 return;
465 }
466
467 probeSymbol = list[1];
468 if (probeSymbol == sym) {
469 thisBucket->symbolP = (OSSymbol **) list[0];
470 kfree(list, 2 * sizeof(OSSymbol *));
471 OSMETA_ACCUMSIZE(-(2 * sizeof(OSSymbol *)));
472 count--;
473 thisBucket->count--;
474 SHRINK_POOL();
475 return;
476 }
477 // couldn't find the symbol; probably means string hash changed
478 panic("removeSymbol %s count %d ", sym->string ? sym->string : "no string", count);
479 return;
480 }
481
482 for (; j--; list++) {
483 probeSymbol = *list;
484 if (probeSymbol == sym) {
485 list = (OSSymbol **)
486 kalloc_tag((thisBucket->count - 1) * sizeof(OSSymbol *), VM_KERN_MEMORY_LIBKERN);
487 OSMETA_ACCUMSIZE((thisBucket->count - 1) * sizeof(OSSymbol *));
488 if (thisBucket->count - 1 != j) {
489 bcopy(thisBucket->symbolP, list,
490 (thisBucket->count - 1 - j) * sizeof(OSSymbol *));
491 }
492 if (j) {
493 bcopy(thisBucket->symbolP + thisBucket->count - j,
494 list + thisBucket->count - 1 - j,
495 j * sizeof(OSSymbol *));
496 }
497 kfree(thisBucket->symbolP, thisBucket->count * sizeof(OSSymbol *));
498 OSMETA_ACCUMSIZE(-(thisBucket->count * sizeof(OSSymbol *)));
499 thisBucket->symbolP = list;
500 count--;
501 thisBucket->count--;
502 return;
503 }
504 }
6d2010ae 505 // couldn't find the symbol; probably means string hash changed
0a7de745 506 panic("removeSymbol %s count %d ", sym->string ? sym->string : "no string", count);
1c79356b
A
507}
508
509/*
510 *********************************************************************
511 * From here on we are actually implementing the OSSymbol class
512 *********************************************************************
513 */
f427ee49
A
514OSDefineMetaClassAndStructorsWithInitAndZone(OSSymbol, OSString,
515 OSSymbol::initialize(), ZC_ZFREE_CLEARMEM)
1c79356b
A
516OSMetaClassDefineReservedUnused(OSSymbol, 0);
517OSMetaClassDefineReservedUnused(OSSymbol, 1);
518OSMetaClassDefineReservedUnused(OSSymbol, 2);
519OSMetaClassDefineReservedUnused(OSSymbol, 3);
520OSMetaClassDefineReservedUnused(OSSymbol, 4);
521OSMetaClassDefineReservedUnused(OSSymbol, 5);
522OSMetaClassDefineReservedUnused(OSSymbol, 6);
523OSMetaClassDefineReservedUnused(OSSymbol, 7);
524
525static OSSymbolPool *pool;
526
0a7de745
A
527void
528OSSymbol::initialize()
1c79356b 529{
0a7de745
A
530 pool = new OSSymbolPool;
531 assert(pool);
1c79356b 532
0a7de745
A
533 if (pool && !pool->init()) {
534 delete pool;
535 assert(false);
536 }
537 ;
1c79356b
A
538}
539
0a7de745
A
540bool
541OSSymbol::initWithCStringNoCopy(const char *)
542{
543 return false;
544}
545bool
546OSSymbol::initWithCString(const char *)
547{
548 return false;
549}
550bool
551OSSymbol::initWithString(const OSString *)
552{
553 return false;
554}
555
f427ee49 556OSSharedPtr<const OSSymbol>
0a7de745
A
557OSSymbol::withString(const OSString *aString)
558{
559 // This string may be a OSSymbol already, cheap check.
560 if (OSDynamicCast(OSSymbol, aString)) {
f427ee49
A
561 OSSharedPtr<const OSSymbol> aStringNew((const OSSymbol *)aString, OSRetain);
562 return aStringNew;
0a7de745
A
563 } else if (((const OSSymbol *) aString)->flags & kOSStringNoCopy) {
564 return OSSymbol::withCStringNoCopy(aString->getCStringNoCopy());
565 } else {
566 return OSSymbol::withCString(aString->getCStringNoCopy());
567 }
568}
569
f427ee49 570OSSharedPtr<const OSSymbol>
0a7de745
A
571OSSymbol::withCString(const char *cString)
572{
f427ee49 573 OSSharedPtr<const OSSymbol> symbol;
0a7de745
A
574
575 // Check if the symbol exists already, we don't need to take a lock here,
576 // since existingSymbolForCString will take the shared lock.
577 symbol = OSSymbol::existingSymbolForCString(cString);
578 if (symbol) {
579 return symbol;
580 }
581
f427ee49 582 OSSharedPtr<OSSymbol> newSymb = OSMakeShared<OSSymbol>();
0a7de745 583 if (!newSymb) {
f427ee49 584 return os::move(newSymb);
0a7de745
A
585 }
586
587 if (newSymb->OSString::initWithCString(cString)) {
588 pool->closeWriteGate();
f427ee49 589 symbol = pool->insertSymbol(newSymb.get());
0a7de745
A
590 pool->openWriteGate();
591
592 if (symbol) {
593 // Somebody must have inserted the new symbol so free our copy
f427ee49 594 newSymb.detach()->OSString::free();
0a7de745
A
595 return symbol;
596 }
597 }
598
f427ee49 599 return os::move(newSymb); // return the newly created & inserted symbol.
1c79356b
A
600}
601
f427ee49 602OSSharedPtr<const OSSymbol>
0a7de745
A
603OSSymbol::withCStringNoCopy(const char *cString)
604{
f427ee49
A
605 OSSharedPtr<const OSSymbol> symbol;
606 OSSharedPtr<OSSymbol> newSymb;
0a7de745
A
607
608 // Check if the symbol exists already, we don't need to take a lock here,
609 // since existingSymbolForCString will take the shared lock.
610 symbol = OSSymbol::existingSymbolForCString(cString);
611 if (symbol) {
612 return symbol;
613 }
614
f427ee49 615 newSymb = OSMakeShared<OSSymbol>();
0a7de745 616 if (!newSymb) {
f427ee49 617 return os::move(newSymb);
0a7de745
A
618 }
619
620 if (newSymb->OSString::initWithCStringNoCopy(cString)) {
621 pool->closeWriteGate();
f427ee49 622 symbol = pool->insertSymbol(newSymb.get());
0a7de745
A
623 pool->openWriteGate();
624
625 if (symbol) {
f427ee49 626 newSymb.detach()->OSString::free();
0a7de745 627 // Somebody must have inserted the new symbol so free our copy
0a7de745
A
628 return symbol;
629 }
630 }
631
f427ee49 632 return os::move(newSymb); // return the newly created & inserted symbol.
1c79356b
A
633}
634
f427ee49 635OSSharedPtr<const OSSymbol>
0a7de745
A
636OSSymbol::existingSymbolForString(const OSString *aString)
637{
638 if (OSDynamicCast(OSSymbol, aString)) {
f427ee49
A
639 OSSharedPtr<const OSSymbol> aStringNew((const OSSymbol *)aString, OSRetain);
640 return aStringNew;
0a7de745
A
641 }
642
643 return OSSymbol::existingSymbolForCString(aString->getCStringNoCopy());
1c79356b
A
644}
645
f427ee49 646OSSharedPtr<const OSSymbol>
0a7de745 647OSSymbol::existingSymbolForCString(const char *cString)
1c79356b 648{
f427ee49 649 OSSharedPtr<OSSymbol> symbol;
1c79356b 650
0a7de745
A
651 pool->closeReadGate();
652 symbol = pool->findSymbol(cString);
653 pool->openReadGate();
654
f427ee49 655 return os::move(symbol);
1c79356b
A
656}
657
0a7de745
A
658void
659OSSymbol::checkForPageUnload(void *startAddr, void *endAddr)
55e303ae 660{
0a7de745
A
661 OSSymbol *probeSymbol;
662 OSSymbolPoolState state;
663
664 pool->closeWriteGate();
665 state = pool->initHashState();
666 while ((probeSymbol = pool->nextHashState(&state))) {
667 if (probeSymbol->string >= startAddr && probeSymbol->string < endAddr) {
668 probeSymbol->OSString::initWithCString(probeSymbol->string);
669 }
670 }
671 pool->openWriteGate();
55e303ae
A
672}
673
0a7de745
A
674void
675OSSymbol::taggedRelease(const void *tag) const
1c79356b 676{
0a7de745 677 super::taggedRelease(tag);
55e303ae
A
678}
679
0a7de745
A
680void
681OSSymbol::taggedRelease(const void *tag, const int when) const
55e303ae 682{
0a7de745 683 super::taggedRelease(tag, when);
1c79356b
A
684}
685
0a7de745
A
686void
687OSSymbol::free()
1c79356b 688{
0a7de745
A
689 pool->closeWriteGate();
690 pool->removeSymbol(this);
691 pool->openWriteGate();
692 super::free();
1c79356b
A
693}
694
0a7de745
A
695bool
696OSSymbol::isEqualTo(const char *aCString) const
1c79356b 697{
0a7de745 698 return super::isEqualTo(aCString);
1c79356b
A
699}
700
0a7de745
A
701bool
702OSSymbol::isEqualTo(const OSSymbol *aSymbol) const
1c79356b 703{
0a7de745
A
704 return aSymbol == this;
705}
1c79356b 706
0a7de745
A
707bool
708OSSymbol::isEqualTo(const OSMetaClassBase *obj) const
709{
710 OSSymbol * sym;
711 OSString * str;
712
713 if ((sym = OSDynamicCast(OSSymbol, obj))) {
714 return isEqualTo(sym);
715 } else if ((str = OSDynamicCast(OSString, obj))) {
716 return super::isEqualTo(str);
717 } else {
718 return false;
719 }
1c79356b 720}
316670eb
A
721
722unsigned int
723OSSymbol::bsearch(
724 const void * key,
725 const void * array,
726 unsigned int arrayCount,
727 size_t memberSize)
728{
0a7de745
A
729 const void **p;
730 unsigned int baseIdx = 0;
731 unsigned int lim;
732
733 for (lim = arrayCount; lim; lim >>= 1) {
734 p = (typeof(p))(((uintptr_t) array) + (baseIdx + (lim >> 1)) * memberSize);
735 if (key == *p) {
736 return baseIdx + (lim >> 1);
737 }
738 if (key > *p) {
739 // move right
740 baseIdx += (lim >> 1) + 1;
741 lim--;
742 }
743 // else move left
744 }
745 // not found, insertion point here
746 return baseIdx + (lim >> 1);
316670eb 747}