Annotation of XNU/libkern/c++/OSSymbol.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* IOSymbol.cpp created by gvdl on Fri 1998-11-17 */
                     23: 
                     24: #include <sys/cdefs.h>
                     25: 
                     26: __BEGIN_DECLS
                     27: #include <kern/lock.h>
                     28: __END_DECLS
                     29: 
                     30: #include <libkern/c++/OSSymbol.h>
                     31: #include <libkern/c++/OSLib.h>
                     32: 
                     33: #define super OSString
                     34: 
                     35: typedef struct { int i, j; } OSSymbolPoolState;
                     36: 
                     37: #ifdef DEBUG
                     38: extern "C" {
                     39:     extern int debug_container_malloc_size;
                     40: };
                     41: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
                     42: #else
                     43: #define ACCUMSIZE(s)
                     44: #endif
                     45: 
                     46: class OSSymbolPool
                     47: {
                     48: private:
                     49:     static const unsigned int kInitBucketCount = 16;
                     50: 
                     51:     typedef struct { unsigned int count; OSSymbol **symbolP; } Bucket;
                     52: 
                     53:     Bucket *buckets;
                     54:     unsigned int nBuckets;
                     55:     unsigned int count;
                     56:     mutex_t *poolGate;
                     57: 
                     58:     static inline void hashSymbol(const char *s,
                     59:                                   unsigned int *hashP,
                     60:                                   unsigned int *lenP)
                     61:     {
                     62:         unsigned int hash = 0;
                     63:         unsigned int len = 0;
                     64: 
                     65:         /* Unroll the loop. */
                     66:         for (;;) {
                     67:             if (!*s) break; len++; hash ^= *s++;
                     68:             if (!*s) break; len++; hash ^= *s++ <<  8;
                     69:             if (!*s) break; len++; hash ^= *s++ << 16;
                     70:             if (!*s) break; len++; hash ^= *s++ << 24;
                     71:         }
                     72:         *lenP = len;
                     73:         *hashP = hash;
                     74:     }
                     75: 
                     76:     static unsigned long log2(unsigned int x);
                     77:     static unsigned long exp2ml(unsigned int x);
                     78: 
                     79:     void reconstructSymbols();
                     80: 
                     81: public:
                     82:     static void *operator new(size_t size);
                     83:     static void operator delete(void *mem, size_t size);
                     84: 
                     85:     OSSymbolPool() { };
                     86:     OSSymbolPool(const OSSymbolPool *old);
                     87:     virtual ~OSSymbolPool();
                     88: 
                     89:     bool init();
                     90: 
                     91:     inline void closeGate() { mutex_lock(poolGate); };
                     92:     inline void openGate()  { mutex_unlock(poolGate); };
                     93: 
                     94:     OSSymbol *findSymbol(const char *cString) const;
                     95:     OSSymbol *insertSymbol(OSSymbol *sym);
                     96:     void removeSymbol(const char *cString);
                     97: 
                     98:     OSSymbolPoolState initHashState();
                     99:     OSSymbol *nextHashState(OSSymbolPoolState *stateP);
                    100: };
                    101: 
                    102: void * OSSymbolPool::operator new(size_t size)
                    103: {
                    104:     void *mem = (void *)kalloc(size);
                    105:     ACCUMSIZE(size);
                    106:     assert(mem);
                    107:     bzero(mem, size);
                    108: 
                    109:     return mem;
                    110: }
                    111: 
                    112: void OSSymbolPool::operator delete(void *mem, size_t size)
                    113: {
                    114:     kfree((vm_offset_t)mem, size);
                    115:     ACCUMSIZE(-size);
                    116: }
                    117: 
                    118: bool OSSymbolPool::init()
                    119: {
                    120:     count = 0;
                    121:     nBuckets = exp2ml(1 + log2(kInitBucketCount));
                    122:     buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket));
                    123:     ACCUMSIZE(nBuckets * sizeof(Bucket));
                    124:     if (!buckets)
                    125:         return false;
                    126: 
                    127:     bzero(buckets, nBuckets * sizeof(Bucket));
                    128: 
                    129:     poolGate = mutex_alloc(0);
                    130: 
                    131:     return poolGate != 0;
                    132: }
                    133: 
                    134: OSSymbolPool::OSSymbolPool(const OSSymbolPool *old)
                    135: {
                    136:     count = old->count;
                    137:     nBuckets = old->nBuckets;
                    138:     buckets = old->buckets;
                    139: 
                    140:     poolGate = 0;      // Do not duplicate the poolGate
                    141: }
                    142: 
                    143: OSSymbolPool::~OSSymbolPool()
                    144: {
                    145:     if (buckets) {
                    146:         kfree((vm_offset_t)buckets, nBuckets * sizeof(Bucket));
                    147:         ACCUMSIZE(-(nBuckets * sizeof(Bucket)));
                    148:     }
                    149: 
                    150:     if (poolGate)
                    151:         kfree((vm_offset_t) poolGate, 36 * 4);
                    152: }
                    153: 
                    154: unsigned long OSSymbolPool::log2(unsigned int x)
                    155: {
                    156:     unsigned long i;
                    157: 
                    158:     for (i = 0; x > 1 ; i++)
                    159:         x >>= 1;
                    160:     return i;
                    161: }
                    162: 
                    163: unsigned long OSSymbolPool::exp2ml(unsigned int x)
                    164: {
                    165:     return (1 << x) - 1;
                    166: }
                    167: 
                    168: OSSymbolPoolState OSSymbolPool::initHashState()
                    169: {
                    170:     OSSymbolPoolState newState = { nBuckets, 0 };
                    171:     return newState;
                    172: }
                    173: 
                    174: OSSymbol *OSSymbolPool::nextHashState(OSSymbolPoolState *stateP)
                    175: {
                    176:     Bucket *thisBucket = &buckets[stateP->i];
                    177: 
                    178:     while (!stateP->j) {
                    179:         if (!stateP->i)
                    180:             return 0;
                    181:         stateP->i--;
                    182:         thisBucket--;
                    183:         stateP->j = thisBucket->count;
                    184:     }
                    185: 
                    186:     stateP->j--;
                    187:     if (thisBucket->count == 1)
                    188:         return (OSSymbol *) thisBucket->symbolP;
                    189:     else
                    190:         return thisBucket->symbolP[stateP->j];
                    191: }
                    192: 
                    193: void OSSymbolPool::reconstructSymbols()
                    194: {
                    195:     OSSymbolPool old(this);
                    196:     OSSymbol *insert;
                    197:     OSSymbolPoolState state;
                    198: 
                    199:     nBuckets += nBuckets + 1;
                    200:     count = 0;
                    201:     buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket));
                    202:     ACCUMSIZE(nBuckets * sizeof(Bucket));
                    203:     /* @@@ gvdl: Zero test and panic if can't set up pool */
                    204:     bzero(buckets, nBuckets * sizeof(Bucket));
                    205: 
                    206:     state = old.initHashState();
                    207:     while ( (insert = old.nextHashState(&state)) )
                    208:         insertSymbol(insert);
                    209: }
                    210: 
                    211: OSSymbol *OSSymbolPool::findSymbol(const char *cString) const
                    212: {
                    213:     Bucket *thisBucket;
                    214:     unsigned int j, inLen, hash;
                    215:     OSSymbol *probeSymbol, **list;
                    216: 
                    217:     hashSymbol(cString, &hash, &inLen); inLen++;
                    218:     thisBucket = &buckets[hash % nBuckets];
                    219:     j = thisBucket->count;
                    220: 
                    221:     if (!j)
                    222:         return 0;
                    223: 
                    224:     if (j == 1) {
                    225:         probeSymbol = (OSSymbol *) thisBucket->symbolP;
                    226: 
                    227:         if (inLen == probeSymbol->length
                    228:         &&  (strcmp(probeSymbol->string, cString) == 0)
                    229:         &&  (probeSymbol->getRetainCount() >= 1))      // WRONG need when
                    230:             return probeSymbol;
                    231:         else
                    232:             return 0;
                    233:     }
                    234: 
                    235:     for (list = thisBucket->symbolP; j--; list++) {
                    236:         probeSymbol = *list;
                    237:         if (inLen == probeSymbol->length
                    238:         &&  (strcmp(probeSymbol->string, cString) == 0)
                    239:         &&  (probeSymbol->getRetainCount() >= 1))      // WRONG need when
                    240:             return probeSymbol;
                    241:     }
                    242: 
                    243:     return 0;
                    244: }
                    245: 
                    246: OSSymbol *OSSymbolPool::insertSymbol(OSSymbol *sym)
                    247: {
                    248:     const char *cString = sym->string;
                    249:     Bucket *thisBucket;
                    250:     unsigned int j, inLen, hash;
                    251:     OSSymbol *probeSymbol, **list;
                    252: 
                    253:     hashSymbol(cString, &hash, &inLen); inLen++;
                    254:     thisBucket = &buckets[hash % nBuckets];
                    255:     j = thisBucket->count;
                    256: 
                    257:     if (!j) {
                    258:         thisBucket->symbolP = (OSSymbol **) sym;
                    259:         thisBucket->count++;
                    260:         count++;
                    261:         return 0;
                    262:     }
                    263: 
                    264:     if (j == 1) {
                    265:         probeSymbol = (OSSymbol *) thisBucket->symbolP;
                    266: 
                    267:         if (inLen == probeSymbol->length
                    268:         &&  strcmp(probeSymbol->string, cString) == 0)
                    269:             return probeSymbol;
                    270: 
                    271:         list = (OSSymbol **) kalloc(2 * sizeof(OSSymbol *));
                    272:         ACCUMSIZE(2 * sizeof(OSSymbol *));
                    273:         /* @@@ gvdl: Zero test and panic if can't set up pool */
                    274:         list[0] = sym;
                    275:         list[1] = probeSymbol;
                    276:         thisBucket->symbolP = list;
                    277:         thisBucket->count++;
                    278:         count++;
                    279:         if (count > nBuckets)
                    280:             reconstructSymbols();
                    281: 
                    282:         return 0;
                    283:     }
                    284: 
                    285:     for (list = thisBucket->symbolP; j--; list++) {
                    286:         probeSymbol = *list;
                    287:         if (inLen == probeSymbol->length
                    288:         &&  strcmp(probeSymbol->string, cString) == 0)
                    289:             return probeSymbol;
                    290:     }
                    291: 
                    292:     j = thisBucket->count++;
                    293:     count++;
                    294:     list = (OSSymbol **) kalloc(thisBucket->count * sizeof(OSSymbol *));
                    295:     ACCUMSIZE(thisBucket->count * sizeof(OSSymbol *));
                    296:     /* @@@ gvdl: Zero test and panic if can't set up pool */
                    297:     list[0] = sym;
                    298:     bcopy(thisBucket->symbolP, list + 1, j * sizeof(OSSymbol *));
                    299:     kfree((vm_offset_t)thisBucket->symbolP, j * sizeof(OSSymbol *));
                    300:     ACCUMSIZE(-(j * sizeof(OSSymbol *)));
                    301:     thisBucket->symbolP = list;
                    302:     if (count > nBuckets)
                    303:         reconstructSymbols();
                    304: 
                    305:     return 0;
                    306: }
                    307: 
                    308: void OSSymbolPool::removeSymbol(const char *cString)
                    309: {
                    310:     Bucket *thisBucket;
                    311:     unsigned int j, inLen, hash;
                    312:     OSSymbol *probeSymbol, **list;
                    313: 
                    314:     hashSymbol(cString, &hash, &inLen); inLen++;
                    315:     thisBucket = &buckets[hash % nBuckets];
                    316:     j = thisBucket->count;
                    317:     list = thisBucket->symbolP;
                    318: 
                    319:     if (!j)
                    320:         return;
                    321: 
                    322:     if (j == 1) {
                    323:         probeSymbol = (OSSymbol *) list;
                    324: 
                    325:         if (inLen == probeSymbol->length
                    326:         &&  strcmp(probeSymbol->string, cString) == 0) {
                    327:             thisBucket->symbolP = 0;
                    328:             count--;
                    329:             thisBucket->count--;
                    330:             return;
                    331:         }
                    332:         return;
                    333:     }
                    334: 
                    335:     if (j == 2) {
                    336:         probeSymbol = list[0];
                    337:         if (inLen == probeSymbol->length
                    338:         &&  strcmp(probeSymbol->string, cString) == 0) {
                    339:             thisBucket->symbolP = (OSSymbol **) list[1];
                    340:             kfree((vm_offset_t)list, 2 * sizeof(OSSymbol *));
                    341:            ACCUMSIZE(-(2 * sizeof(OSSymbol *)));
                    342:             count--;
                    343:             thisBucket->count--;
                    344:             return;
                    345:         }
                    346: 
                    347:         probeSymbol = list[1];
                    348:         if (inLen == probeSymbol->length
                    349:         &&  strcmp(probeSymbol->string, cString) == 0) {
                    350:             thisBucket->symbolP = (OSSymbol **) list[0];
                    351:             kfree((vm_offset_t)list, 2 * sizeof(OSSymbol *));
                    352:            ACCUMSIZE(-(2 * sizeof(OSSymbol *)));
                    353:             count--;
                    354:             thisBucket->count--;
                    355:             return;
                    356:         }
                    357:         return;
                    358:     }
                    359: 
                    360:     for (; j--; list++) {
                    361:         probeSymbol = *list;
                    362:         if (inLen == probeSymbol->length
                    363:         &&  strcmp(probeSymbol->string, cString) == 0) {
                    364: 
                    365:             list = (OSSymbol **)
                    366:                 kalloc((thisBucket->count-1) * sizeof(OSSymbol *));
                    367:            ACCUMSIZE((thisBucket->count-1) * sizeof(OSSymbol *));
                    368:             if (thisBucket->count-1 != j)
                    369:                 bcopy(thisBucket->symbolP, list,
                    370:                       (thisBucket->count-1-j) * sizeof(OSSymbol *));
                    371:             if (j)
                    372:                 bcopy(thisBucket->symbolP + thisBucket->count-j,
                    373:                       list + thisBucket->count-1-j,
                    374:                       j * sizeof(OSSymbol *));
                    375:             kfree((vm_offset_t)thisBucket->symbolP, thisBucket->count * sizeof(OSSymbol *));
                    376:            ACCUMSIZE(-(thisBucket->count * sizeof(OSSymbol *)));
                    377:             thisBucket->symbolP = list;
                    378:             count--;
                    379:             thisBucket->count--;
                    380:             return;
                    381:         }
                    382:     }
                    383: }
                    384: 
                    385: /*
                    386:  *********************************************************************
                    387:  * From here on we are actually implementing the OSSymbol class
                    388:  *********************************************************************
                    389:  */
                    390: OSDefineMetaClassAndStructorsWithInit(OSSymbol, OSString,
                    391:                                       OSSymbol::initialize())
                    392: 
                    393: static OSSymbolPool *pool;
                    394: 
                    395: void OSSymbol::initialize()
                    396: {
                    397:     pool = new OSSymbolPool;
                    398:     assert(pool);
                    399: 
                    400:     if (!pool->init()) {
                    401:         delete pool;
                    402:         assert(false);
                    403:     };
                    404: }
                    405: 
                    406: bool OSSymbol::initWithCStringNoCopy(const char *) { return false; }
                    407: bool OSSymbol::initWithCString(const char *) { return false; }
                    408: bool OSSymbol::initWithString(const OSString *) { return false; }
                    409: 
                    410: const OSSymbol *OSSymbol::withString(const OSString *aString)
                    411: {
                    412:     if (((const OSSymbol *) aString)->flags & kOSStringNoCopy)
                    413:         return OSSymbol::withCStringNoCopy(aString->getCStringNoCopy());
                    414:     else
                    415:         return OSSymbol::withCString(aString->getCStringNoCopy());
                    416: }
                    417: 
                    418: const OSSymbol *OSSymbol::withCString(const char *cString)
                    419: {
                    420:     pool->closeGate();
                    421: 
                    422:     OSSymbol *newSymb = pool->findSymbol(cString);
                    423:     if (newSymb)
                    424:         newSymb->retain();
                    425:     else if ( (newSymb = new OSSymbol) ) {
                    426:        if (newSymb->OSString::initWithCString(cString))
                    427:            pool->insertSymbol(newSymb);
                    428:        else {
                    429:            newSymb->free();
                    430:            newSymb = 0;
                    431:        }
                    432:     }
                    433:     pool->openGate();
                    434: 
                    435:     return newSymb;
                    436: }
                    437: 
                    438: const OSSymbol *OSSymbol::withCStringNoCopy(const char *cString)
                    439: {
                    440:     pool->closeGate();
                    441: 
                    442:     OSSymbol *newSymb = pool->findSymbol(cString);
                    443:     if (newSymb)
                    444:         newSymb->retain();
                    445:     else if ( (newSymb = new OSSymbol) ) {
                    446:        if (newSymb->OSString::initWithCStringNoCopy(cString))
                    447:            pool->insertSymbol(newSymb);
                    448:        else {
                    449:            newSymb->free();
                    450:            newSymb = 0;
                    451:        }
                    452:     }
                    453:     pool->openGate();
                    454: 
                    455:     return newSymb;
                    456: }
                    457: 
                    458: void OSSymbol::checkForPageUnload(void *startAddr, void *endAddr)
                    459: {
                    460:     OSSymbol *probeSymbol;
                    461:     OSSymbolPoolState state;
                    462: 
                    463:     pool->closeGate();
                    464:     state = pool->initHashState();
                    465:     while ( (probeSymbol = pool->nextHashState(&state)) ) {
                    466:         if (probeSymbol->string >= startAddr || probeSymbol->string < endAddr) {
                    467:             const char *oldString = probeSymbol->string;
                    468: 
                    469:             probeSymbol->string = (char *) kalloc(probeSymbol->length);
                    470:            ACCUMSIZE(probeSymbol->length);
                    471:             bcopy(oldString, probeSymbol->string, probeSymbol->length);
                    472:             probeSymbol->flags &= ~kOSStringNoCopy;
                    473:         }
                    474:     }
                    475:     pool->openGate();
                    476: }
                    477: 
                    478: void OSSymbol::free()
                    479: {
                    480:     pool->closeGate();
                    481:     pool->removeSymbol(string);
                    482:     pool->openGate();
                    483:     
                    484:     super::free();
                    485: }
                    486: 
                    487: bool OSSymbol::isEqualTo(const char *aCString) const
                    488: {
                    489:     return super::isEqualTo(aCString);
                    490: }
                    491: 
                    492: bool OSSymbol::isEqualTo(const OSSymbol *aSymbol) const
                    493: {
                    494:     return aSymbol == this;
                    495: }
                    496: 
                    497: bool OSSymbol::isEqualTo(const OSObject *obj) const
                    498: {
                    499:     OSSymbol * sym;
                    500:     OSString * str;
                    501: 
                    502:     if ((sym = OSDynamicCast(OSSymbol, (OSObject *)obj )))
                    503:        return isEqualTo(sym);
                    504:     else if ((str = OSDynamicCast(OSString, (OSObject *)obj )))
                    505:        return super::isEqualTo(str);
                    506:     else
                    507:        return false;
                    508: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.