Annotation of XNU/libkern/c++/OSSymbol.cpp, revision 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.