|
|
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: /* OSMetaClass.cpp created by gvdl on Fri 1998-11-17 */ ! 23: ! 24: #include <string.h> ! 25: #include <sys/systm.h> ! 26: ! 27: #include <libkern/OSReturn.h> ! 28: ! 29: #include <libkern/c++/OSCollectionIterator.h> ! 30: #include <libkern/c++/OSDictionary.h> ! 31: #include <libkern/c++/OSMetaClass.h> ! 32: #include <libkern/c++/OSArray.h> ! 33: #include <libkern/c++/OSSet.h> ! 34: #include <libkern/c++/OSSymbol.h> ! 35: #include <libkern/c++/OSNumber.h> ! 36: #include <libkern/c++/OSSerialize.h> ! 37: #include <libkern/c++/OSLib.h> ! 38: ! 39: enum { ! 40: kSuperIsCString = 0x80000000, ! 41: }; ! 42: ! 43: __BEGIN_DECLS ! 44: ! 45: #include <mach/etap_events.h> ! 46: #include <kern/lock.h> ! 47: ! 48: #ifdef DEBUG ! 49: extern int debug_container_malloc_size; ! 50: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) ! 51: #else ! 52: #define ACCUMSIZE(s) ! 53: #endif /* DEBUG */ ! 54: ! 55: __END_DECLS ! 56: ! 57: static enum { ! 58: kCompletedBootstrap = 0, ! 59: kNoDictionaries = 1, ! 60: kMakingDictionaries = 2 ! 61: } sBootstrapState = kNoDictionaries; ! 62: ! 63: static const int kClassCapacityIncrement = 40; ! 64: static const int kKModCapacityIncrement = 10; ! 65: static OSDictionary *sAllClassesDict, *sKModClassesDict; ! 66: ! 67: static mutex_t *loadLock; ! 68: static struct StalledData { ! 69: const char *kmodName; ! 70: OSReturn result; ! 71: unsigned int capacity; ! 72: unsigned int count; ! 73: OSMetaClass **classes; ! 74: } *sStalled; ! 75: ! 76: void OSMetaClass::logError(OSReturn result) ! 77: { ! 78: const char *msg; ! 79: ! 80: switch (result) { ! 81: case kOSMetaClassNoInit: ! 82: msg="OSMetaClass::preModLoad wasn't called, runtime internal error"; ! 83: break; ! 84: case kOSMetaClassNoDicts: ! 85: msg="Allocation failure for Metaclass internal dictionaries"; break; ! 86: case kOSMetaClassNoKModSet: ! 87: msg="Allocation failure for internal kmodule set"; break; ! 88: case kOSMetaClassNoInsKModSet: ! 89: msg="Can't insert the KMod set into the module dictionary"; break; ! 90: case kOSMetaClassNoSuper: ! 91: msg="Can't associate a class with its super class"; break; ! 92: case kOSMetaClassInstNoSuper: ! 93: msg="Instance construction, unknown super class."; break; ! 94: default: ! 95: case kOSMetaClassInternal: ! 96: msg="runtime internal error"; break; ! 97: case kOSReturnSuccess: ! 98: return; ! 99: } ! 100: printf("%s\n", msg); ! 101: } ! 102: ! 103: OSMetaClass::OSMetaClass(const char *inClassName, ! 104: const char *inSuperClassName, ! 105: unsigned int inClassSize) ! 106: { ! 107: instanceCount = 0; ! 108: classSize = inClassSize; ! 109: if (inSuperClassName && *inSuperClassName) { ! 110: superClass = (OSMetaClass *) inSuperClassName; ! 111: classSize |= kSuperIsCString; ! 112: } ! 113: else ! 114: superClass = 0; ! 115: ! 116: className = (const OSSymbol *) inClassName; ! 117: ! 118: if (!sStalled) { ! 119: printf("OSMetaClass::preModLoad wasn't called for %s, " ! 120: "runtime internal error\n", inClassName); ! 121: } else if (!sStalled->result) { ! 122: // Grow stalled array if neccessary ! 123: if (sStalled->count >= sStalled->capacity) { ! 124: OSMetaClass **oldStalled = sStalled->classes; ! 125: int oldSize = sStalled->capacity * sizeof(OSMetaClass *); ! 126: int newSize = oldSize ! 127: + kKModCapacityIncrement * sizeof(OSMetaClass *); ! 128: ! 129: sStalled->classes = (OSMetaClass **) kalloc(newSize); ! 130: if (!sStalled->classes) { ! 131: sStalled->classes = oldStalled; ! 132: sStalled->result = kOSMetaClassNoTempData; ! 133: return; ! 134: } ! 135: ! 136: sStalled->capacity += kKModCapacityIncrement; ! 137: memmove(sStalled->classes, oldStalled, oldSize); ! 138: kfree((vm_offset_t)oldStalled, oldSize); ! 139: ACCUMSIZE(newSize - oldSize); ! 140: } ! 141: ! 142: sStalled->classes[sStalled->count++] = this; ! 143: } ! 144: } ! 145: ! 146: OSMetaClass::~OSMetaClass() ! 147: { ! 148: do { ! 149: OSCollectionIterator *iter; ! 150: ! 151: if (sAllClassesDict) ! 152: sAllClassesDict->removeObject(className); ! 153: ! 154: iter = OSCollectionIterator::withCollection(sKModClassesDict); ! 155: if (!iter) ! 156: break; ! 157: ! 158: OSSymbol *iterKey; ! 159: while ( (iterKey = (OSSymbol *) iter->getNextObject()) ) { ! 160: OSSet *kmodClassSet; ! 161: kmodClassSet = (OSSet *) sKModClassesDict->getObject(iterKey); ! 162: if (kmodClassSet && kmodClassSet->containsObject(this)) { ! 163: kmodClassSet->removeObject(this); ! 164: break; ! 165: } ! 166: } ! 167: iter->release(); ! 168: } while (false); ! 169: ! 170: if (sStalled) { ! 171: unsigned int i; ! 172: ! 173: // First pass find class in stalled list ! 174: for (i = 0; i < sStalled->count; i++) ! 175: if (this == sStalled->classes[i]) ! 176: break; ! 177: ! 178: if (i < sStalled->count) { ! 179: sStalled->count--; ! 180: if (i < sStalled->count) ! 181: memmove(&sStalled->classes[i], &sStalled->classes[i+1], ! 182: (sStalled->count - i) * sizeof(OSMetaClass *)); ! 183: } ! 184: return; ! 185: } ! 186: } ! 187: ! 188: // Don't do anything as these classes must be statically allocated ! 189: void OSMetaClass::free() { } ! 190: void OSMetaClass::retain() { } ! 191: void OSMetaClass::release() { } ! 192: ! 193: const char *OSMetaClass::getClassName() const ! 194: { ! 195: return className->getCStringNoCopy(); ! 196: } ! 197: ! 198: unsigned int OSMetaClass::getClassSize() const ! 199: { ! 200: return classSize & ~kSuperIsCString; ! 201: } ! 202: ! 203: void *OSMetaClass::preModLoad(const char *kmodName) ! 204: { ! 205: if (!loadLock) { ! 206: loadLock = mutex_alloc(ETAP_IO_AHA); ! 207: _mutex_lock(loadLock); ! 208: } ! 209: else ! 210: _mutex_lock(loadLock); ! 211: ! 212: sStalled = (StalledData *) kalloc(sizeof(*sStalled)); ! 213: if (sStalled) { ! 214: sStalled->classes = (OSMetaClass **) ! 215: kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); ! 216: if (!sStalled->classes) { ! 217: kfree((vm_offset_t) sStalled, sizeof(*sStalled)); ! 218: return 0; ! 219: } ! 220: ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled)); ! 221: ! 222: sStalled->result = kOSReturnSuccess; ! 223: sStalled->capacity = kKModCapacityIncrement; ! 224: sStalled->count = 0; ! 225: sStalled->kmodName = kmodName; ! 226: bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); ! 227: } ! 228: ! 229: return sStalled; ! 230: } ! 231: ! 232: bool OSMetaClass::checkModLoad(void *loadHandle) ! 233: { ! 234: return sStalled && loadHandle == sStalled ! 235: && sStalled->result == kOSReturnSuccess; ! 236: } ! 237: ! 238: static inline const OSSymbol *copySymbol(bool copy, const char *cString) ! 239: { ! 240: if (copy) ! 241: return OSSymbol::withCString(cString); ! 242: else ! 243: return OSSymbol::withCStringNoCopy(cString); ! 244: } ! 245: ! 246: OSReturn OSMetaClass::postModLoad(void *loadHandle) ! 247: { ! 248: OSReturn result = kOSReturnSuccess; ! 249: OSSet *kmodSet = 0; ! 250: ! 251: if (!sStalled || loadHandle != sStalled) { ! 252: logError(kOSMetaClassInternal); ! 253: return kOSMetaClassInternal; ! 254: } ! 255: ! 256: if (sStalled->result) ! 257: result = sStalled->result; ! 258: else switch (sBootstrapState) { ! 259: case kNoDictionaries: ! 260: sBootstrapState = kMakingDictionaries; ! 261: // No break; fall through ! 262: ! 263: case kMakingDictionaries: ! 264: sKModClassesDict = OSDictionary::withCapacity(kKModCapacityIncrement); ! 265: sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); ! 266: if (!sAllClassesDict || !sKModClassesDict) { ! 267: result = kOSMetaClassNoDicts; ! 268: break; ! 269: } ! 270: // No break; fall through ! 271: ! 272: case kCompletedBootstrap: ! 273: { ! 274: bool copyStrings = (0 != strcmp("__kernel__", sStalled->kmodName)); ! 275: ! 276: if (!sStalled->count) ! 277: break; // Nothing to do so just get out ! 278: ! 279: kmodSet = OSSet::withCapacity(sStalled->count); ! 280: if (!kmodSet) { ! 281: result = kOSMetaClassNoKModSet; ! 282: break; ! 283: } ! 284: ! 285: if (!sKModClassesDict->setObject(sStalled->kmodName, kmodSet)) { ! 286: result = kOSMetaClassNoInsKModSet; ! 287: break; ! 288: } ! 289: ! 290: // First pass symbolling strings and inserting classes in dictionary ! 291: for (unsigned int i = 0; i < sStalled->count; i++) { ! 292: OSMetaClass *me = sStalled->classes[i]; ! 293: ! 294: me->className = copySymbol(copyStrings, ! 295: (const char *) me->className); ! 296: if (me->classSize & kSuperIsCString) ! 297: me->superClass = (OSMetaClass *) ! 298: copySymbol(copyStrings, (const char *) me->superClass); ! 299: ! 300: sAllClassesDict->setObject(me->className, me); ! 301: kmodSet->setObject(me); ! 302: } ! 303: ! 304: // Second pass to connect up superclasses. ! 305: for (unsigned int i = 0; !result && i < sStalled->count; i++) { ! 306: OSMetaClass *me = sStalled->classes[i]; ! 307: OSSymbol *superSym; ! 308: ! 309: if (me->classSize & kSuperIsCString) { ! 310: ! 311: me->classSize &= ~kSuperIsCString; ! 312: superSym = (OSSymbol *) me->superClass; ! 313: me->superClass = (OSMetaClass *) ! 314: sAllClassesDict->getObject(superSym); ! 315: superSym->release(); ! 316: if (!me->superClass) ! 317: result = kOSMetaClassNoSuper; ! 318: } ! 319: } ! 320: sBootstrapState = kCompletedBootstrap; ! 321: break; ! 322: } ! 323: ! 324: default: ! 325: result = kOSMetaClassInternal; ! 326: break; ! 327: } ! 328: ! 329: if (kmodSet) ! 330: kmodSet->release(); ! 331: ! 332: if (sStalled) { ! 333: ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) ! 334: + sizeof(*sStalled))); ! 335: kfree((vm_offset_t) sStalled->classes, ! 336: sStalled->capacity * sizeof(OSMetaClass *)); ! 337: kfree((vm_offset_t) sStalled, sizeof(*sStalled)); ! 338: sStalled = 0; ! 339: } ! 340: ! 341: logError(result); ! 342: mutex_unlock(loadLock); ! 343: return result; ! 344: } ! 345: ! 346: ! 347: void OSMetaClass::instanceConstructed() const ! 348: { ! 349: if (sStalled && (classSize & kSuperIsCString) && superClass) ! 350: { ! 351: OSMetaClass *me = (OSMetaClass *) this; // overide const this ! 352: const char * const superName = (const char *) superClass; ! 353: ! 354: // The superClass may be in the class dictionary already. ! 355: if (sBootstrapState == kCompletedBootstrap && sAllClassesDict) ! 356: me->superClass = (OSMetaClass *) ! 357: sAllClassesDict->getObject(superName); ! 358: else ! 359: me->superClass = 0; ! 360: ! 361: if (!me->superClass) { ! 362: // Oh dear we have to scan the stalled list and walk the ! 363: // the super class chain manually. ! 364: unsigned int i; ! 365: ! 366: // find superclass in stalled list ! 367: for (i = 0; i < sStalled->count; i++) { ! 368: if (0 == strcmp(superName, ! 369: (const char *) sStalled->classes[i]->className)) ! 370: break; ! 371: } ! 372: ! 373: if (i < sStalled->count) { ! 374: me->superClass = sStalled->classes[i]; ! 375: me->classSize &= ~kSuperIsCString; ! 376: } ! 377: else ! 378: sStalled->result = kOSMetaClassInstNoSuper; ! 379: ! 380: } ! 381: } ! 382: ! 383: if ((0 == instanceCount++) && superClass) ! 384: superClass->instanceConstructed(); ! 385: } ! 386: ! 387: void OSMetaClass::instanceDestructed() const ! 388: { ! 389: if ((1 == instanceCount--) && superClass) ! 390: superClass->instanceDestructed(); ! 391: ! 392: if( ((int) instanceCount) < 0) ! 393: printf("%s: bad retain(%d)", getClassName(), instanceCount); ! 394: } ! 395: ! 396: bool OSMetaClass::modHasInstance(const char *kmodName) ! 397: { ! 398: bool result = false; ! 399: ! 400: if (!loadLock) { ! 401: loadLock = mutex_alloc(ETAP_IO_AHA); ! 402: _mutex_lock(loadLock); ! 403: } ! 404: else ! 405: _mutex_lock(loadLock); ! 406: ! 407: do { ! 408: OSSet *kmodClasses; ! 409: OSCollectionIterator *iter; ! 410: OSMetaClass *checkClass; ! 411: ! 412: kmodClasses = OSDynamicCast(OSSet, ! 413: sKModClassesDict->getObject(kmodName)); ! 414: if (!kmodClasses) ! 415: break; ! 416: ! 417: iter = OSCollectionIterator::withCollection(kmodClasses); ! 418: if (!iter) ! 419: break; ! 420: ! 421: while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) ! 422: if (checkClass->getInstanceCount()) { ! 423: result = true; ! 424: break; ! 425: } ! 426: ! 427: iter->release(); ! 428: } while (false); ! 429: ! 430: mutex_unlock(loadLock); ! 431: ! 432: return result; ! 433: } ! 434: ! 435: void OSMetaClass::reportModInstances(const char *kmodName) ! 436: { ! 437: OSSet *kmodClasses; ! 438: OSCollectionIterator *iter; ! 439: OSMetaClass *checkClass; ! 440: ! 441: kmodClasses = OSDynamicCast(OSSet, ! 442: sKModClassesDict->getObject(kmodName)); ! 443: if (!kmodClasses) ! 444: return; ! 445: ! 446: iter = OSCollectionIterator::withCollection(kmodClasses); ! 447: if (!iter) ! 448: return; ! 449: ! 450: while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) ! 451: if (checkClass->getInstanceCount()) { ! 452: printf("%s: %s has %d instance(s)\n", ! 453: kmodName, ! 454: checkClass->getClassName(), ! 455: checkClass->getInstanceCount()); ! 456: } ! 457: ! 458: iter->release(); ! 459: } ! 460: ! 461: const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSSymbol *name) ! 462: { ! 463: OSMetaClass *retMeta = 0; ! 464: ! 465: if (!name) ! 466: return 0; ! 467: ! 468: if (sAllClassesDict) ! 469: retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); ! 470: ! 471: if (!retMeta && sStalled) ! 472: { ! 473: // Oh dear we have to scan the stalled list and walk the ! 474: // the stalled list manually. ! 475: const char *cName = name->getCStringNoCopy(); ! 476: unsigned int i; ! 477: ! 478: // find class in stalled list ! 479: for (i = 0; i < sStalled->count; i++) { ! 480: retMeta = sStalled->classes[i]; ! 481: if (0 == strcmp(cName, (const char *) retMeta->className)) ! 482: break; ! 483: } ! 484: ! 485: if (i < sStalled->count) ! 486: retMeta = 0; ! 487: } ! 488: ! 489: return retMeta; ! 490: } ! 491: ! 492: const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSString *name) ! 493: { ! 494: const OSSymbol *tmpKey = OSSymbol::withString(name); ! 495: const OSMetaClass *ret = getMetaClassWithName(tmpKey); ! 496: ! 497: tmpKey->release(); ! 498: return ret; ! 499: } ! 500: ! 501: const OSMetaClass *OSMetaClass::getMetaClassWithName(const char *name) ! 502: { ! 503: const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name); ! 504: const OSMetaClass *ret = getMetaClassWithName(tmpKey); ! 505: ! 506: tmpKey->release(); ! 507: return ret; ! 508: } ! 509: ! 510: OSObject *OSMetaClass::allocClassWithName(const OSSymbol *name) ! 511: { ! 512: const OSMetaClass * const meta = getMetaClassWithName(name); ! 513: ! 514: if (meta) ! 515: return meta->alloc(); ! 516: ! 517: return 0; ! 518: } ! 519: ! 520: OSObject *OSMetaClass::allocClassWithName(const OSString *name) ! 521: { ! 522: const OSMetaClass * const meta = getMetaClassWithName(name); ! 523: ! 524: if (meta) ! 525: return meta->alloc(); ! 526: ! 527: return 0; ! 528: } ! 529: ! 530: OSObject *OSMetaClass::allocClassWithName(const char *name) ! 531: { ! 532: const OSMetaClass * const meta = getMetaClassWithName(name); ! 533: ! 534: if (meta) ! 535: return meta->alloc(); ! 536: ! 537: return 0; ! 538: } ! 539: ! 540: ! 541: OSObject * ! 542: OSMetaClass::checkMetaCastWithName(const OSSymbol *name, const OSObject *in) ! 543: { ! 544: const OSMetaClass * const meta = getMetaClassWithName(name); ! 545: ! 546: if (meta) ! 547: return meta->checkMetaCast(in); ! 548: ! 549: return 0; ! 550: } ! 551: ! 552: OSObject * ! 553: OSMetaClass::checkMetaCastWithName(const OSString *name, const OSObject *in) ! 554: { ! 555: const OSMetaClass * const meta = getMetaClassWithName(name); ! 556: ! 557: if (meta) ! 558: return meta->checkMetaCast(in); ! 559: ! 560: return 0; ! 561: } ! 562: ! 563: OSObject * ! 564: OSMetaClass::checkMetaCastWithName(const char *name, const OSObject *in) ! 565: { ! 566: const OSMetaClass * const meta = getMetaClassWithName(name); ! 567: ! 568: if (meta) ! 569: return meta->checkMetaCast(in); ! 570: ! 571: return 0; ! 572: } ! 573: ! 574: /* ! 575: OSMetaClass::checkMetaCast ! 576: checkMetaCast(OSObject *check) ! 577: ! 578: Check to see if the 'check' object has this object in it's metaclass chain. Returns check if it is indeed a kind of the current meta class, 0 otherwise. ! 579: ! 580: Generally this method is not invoked directly but is used to implement the OSObject::metaCast member function. ! 581: ! 582: See also OSObject::metaCast ! 583: ! 584: */ ! 585: OSObject *OSMetaClass::checkMetaCast(const OSObject *check) const ! 586: { ! 587: const OSMetaClass * const toMeta = this; ! 588: const OSMetaClass *fromMeta; ! 589: ! 590: for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClass) { ! 591: if (toMeta == fromMeta) ! 592: return (OSObject *) check; // Discard const ! 593: ! 594: if (!fromMeta->superClass || (fromMeta->classSize & kSuperIsCString)) ! 595: break; ! 596: } ! 597: ! 598: return 0; ! 599: } ! 600: ! 601: const OSMetaClass *OSMetaClass::getSuperClass() const ! 602: { ! 603: return superClass; ! 604: } ! 605: ! 606: unsigned int OSMetaClass::getInstanceCount() const ! 607: { ! 608: return instanceCount; ! 609: } ! 610: ! 611: void OSMetaClass::printInstanceCounts() ! 612: { ! 613: OSCollectionIterator *classes; ! 614: OSSymbol *className; ! 615: OSMetaClass *meta; ! 616: ! 617: classes = OSCollectionIterator::withCollection(sAllClassesDict); ! 618: if (!classes) ! 619: return; ! 620: ! 621: while( (className = (OSSymbol *)classes->getNextObject())) { ! 622: meta = (OSMetaClass *) sAllClassesDict->getObject(className); ! 623: assert(meta); ! 624: ! 625: printf("%24s count: %03d x 0x%03x = 0x%06x\n", ! 626: className->getCStringNoCopy(), ! 627: meta->getInstanceCount(), ! 628: meta->getClassSize(), ! 629: meta->getInstanceCount() * meta->getClassSize() ); ! 630: } ! 631: printf("\n"); ! 632: classes->release(); ! 633: } ! 634: ! 635: OSDictionary * OSMetaClass::getClassDictionary() ! 636: { ! 637: return sAllClassesDict; ! 638: } ! 639: ! 640: bool OSMetaClass::serialize(OSSerialize *s) const ! 641: { ! 642: OSDictionary * dict; ! 643: OSNumber * off; ! 644: bool ok = false; ! 645: ! 646: if (s->previouslySerialized(this)) return true; ! 647: ! 648: dict = 0;// IODictionary::withCapacity(2); ! 649: off = OSNumber::withNumber(getInstanceCount(), 32); ! 650: ! 651: if (dict) { ! 652: dict->setObject("InstanceCount", off ); ! 653: ok = dict->serialize(s); ! 654: } else if( off) ! 655: ok = off->serialize(s); ! 656: ! 657: if (dict) ! 658: dict->release(); ! 659: if (off) ! 660: off->release(); ! 661: ! 662: return ok; ! 663: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.