1 /* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* OSMetaClass.cpp created by gvdl on Fri 1998-11-17 */ 29 30 #include <string.h> 31 32 #include <libkern/OSReturn.h> 33 34 #include <libkern/c++/OSMetaClass.h> 35 36 #include <libkern/c++/OSObject.h> 37 #include <libkern/c++/OSCollectionIterator.h> 38 #include <libkern/c++/OSDictionary.h> 39 #include <libkern/c++/OSArray.h> 40 #include <libkern/c++/OSSet.h> 41 #include <libkern/c++/OSSymbol.h> 42 #include <libkern/c++/OSNumber.h> 43 #include <libkern/c++/OSSerialize.h> 44 #include <libkern/c++/OSLib.h> 45 #include <libkern/OSAtomic.h> 46 47 #include <IOKit/pwr_mgt/RootDomain.h> 48 #include <IOKit/IOMessage.h> 49 50 __BEGIN_DECLS 51 52 #include <sys/systm.h> 53 #include <mach/mach_types.h> 54 #include <kern/lock.h> 55 #include <kern/clock.h> 56 #include <kern/thread_call.h> 57 #include <kern/host.h> 58 #include <mach/kmod.h> 59 #include <mach/mach_interface.h> 60 61 extern void OSRuntimeUnloadCPP(kmod_info_t *ki, void *); 62 63 #if OSALLOCDEBUG 64 extern int debug_container_malloc_size; 65 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 66 #else 67 #define ACCUMSIZE(s) 68 #endif /* OSALLOCDEBUG */ 69 70 __END_DECLS 71 72 static enum { 73 kCompletedBootstrap = 0, 74 kNoDictionaries = 1, 75 kMakingDictionaries = 2 76 } sBootstrapState = kNoDictionaries; 77 78 static const int kClassCapacityIncrement = 40; 79 static const int kKModCapacityIncrement = 10; 80 static OSDictionary *sAllClassesDict, *sKModClassesDict, *sSortedByClassesDict; 81 82 static mutex_t *loadLock = 0; 83 static struct StalledData { 84 const char *kmodName; 85 OSReturn result; 86 unsigned int capacity; 87 unsigned int count; 88 OSMetaClass **classes; 89 } *sStalled; 90 91 static unsigned int sConsiderUnloadDelay = 60; /* secs */ 92 static bool unloadsEnabled = true; // set to false when system going to sleep 93 static thread_call_t unloadCallout = 0; 94 95 static const char OSMetaClassBasePanicMsg[] = 96 "OSMetaClassBase::_RESERVEDOSMetaClassBase%d called\n"; 97 98 #if SLOT_USED 99 void OSMetaClassBase::_RESERVEDOSMetaClassBase0() 100 { panic(OSMetaClassBasePanicMsg, 0); } 101 void OSMetaClassBase::_RESERVEDOSMetaClassBase1() 102 { panic(OSMetaClassBasePanicMsg, 1); } 103 void OSMetaClassBase::_RESERVEDOSMetaClassBase2() 104 { panic(OSMetaClassBasePanicMsg, 2); } 105 #endif /* SLOT_USED */ 106 107 // As these slots are used move them up inside the #if above 108 void OSMetaClassBase::_RESERVEDOSMetaClassBase3() 109 { panic(OSMetaClassBasePanicMsg, 3); } 110 void OSMetaClassBase::_RESERVEDOSMetaClassBase4() 111 { panic(OSMetaClassBasePanicMsg, 4); } 112 void OSMetaClassBase::_RESERVEDOSMetaClassBase5() 113 { panic(OSMetaClassBasePanicMsg, 5); } 114 void OSMetaClassBase::_RESERVEDOSMetaClassBase6() 115 { panic(OSMetaClassBasePanicMsg, 6); } 116 117 /* 118 * These used to be inline in the header but gcc didn't believe us 119 * Now we MUST pull the inline out at least until the compiler is 120 * repaired. 121 */ 122 // Helper inlines for runtime type preprocessor macros 123 OSMetaClassBase *OSMetaClassBase:: 124 safeMetaCast(const OSMetaClassBase *me, const OSMetaClass *toType) 125 { return (me)? me->metaCast(toType) : 0; } 126 127 bool OSMetaClassBase:: 128 checkTypeInst(const OSMetaClassBase *inst, const OSMetaClassBase *typeinst) 129 { 130 const OSMetaClass *toType = OSTypeIDInst(typeinst); 131 return typeinst && inst && (0 != inst->metaCast(toType)); 132 } 133 134 135 // If you need this slot you had better setup an IOCTL style interface. 136 // 'Cause the whole kernel world depends on OSMetaClassBase and YOU 137 // CANT change the VTABLE size ever. 138 void OSMetaClassBase::_RESERVEDOSMetaClassBase7() 139 { panic(OSMetaClassBasePanicMsg, 7); } 140 141 OSMetaClassBase::OSMetaClassBase() 142 { 143 } 144 145 OSMetaClassBase::~OSMetaClassBase() 146 { 147 void **thisVTable; 148 149 thisVTable = (void **) this; 150 *thisVTable = (void *) -1UL; 151 } 152 153 bool OSMetaClassBase::isEqualTo(const OSMetaClassBase *anObj) const 154 { 155 return this == anObj; 156 } 157 158 OSMetaClassBase *OSMetaClassBase::metaCast(const OSMetaClass *toMeta) const 159 { 160 return toMeta->checkMetaCast(this); 161 } 162 163 OSMetaClassBase *OSMetaClassBase::metaCast(const OSSymbol *toMetaSymb) const 164 { 165 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this); 166 } 167 168 OSMetaClassBase *OSMetaClassBase::metaCast(const OSString *toMetaStr) const 169 { 170 const OSSymbol *tempSymb = OSSymbol::withString(toMetaStr); 171 OSMetaClassBase *ret = 0; 172 if (tempSymb) { 173 ret = metaCast(tempSymb); 174 tempSymb->release(); 175 } 176 return ret; 177 } 178 179 OSMetaClassBase *OSMetaClassBase::metaCast(const char *toMetaCStr) const 180 { 181 const OSSymbol *tempSymb = OSSymbol::withCString(toMetaCStr); 182 OSMetaClassBase *ret = 0; 183 if (tempSymb) { 184 ret = metaCast(tempSymb); 185 tempSymb->release(); 186 } 187 return ret; 188 } 189 190 class OSMetaClassMeta : public OSMetaClass 191 { 192 public: 193 OSMetaClassMeta(); 194 OSObject *alloc() const; 195 }; 196 OSMetaClassMeta::OSMetaClassMeta() 197 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass)) 198 { } 199 OSObject *OSMetaClassMeta::alloc() const { return 0; } 200 201 static OSMetaClassMeta sOSMetaClassMeta; 202 203 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta; 204 const OSMetaClass * OSMetaClass::getMetaClass() const 205 { return &sOSMetaClassMeta; } 206 207 static const char OSMetaClassPanicMsg[] = 208 "OSMetaClass::_RESERVEDOSMetaClass%d called\n"; 209 210 void OSMetaClass::_RESERVEDOSMetaClass0() 211 { panic(OSMetaClassPanicMsg, 0); } 212 void OSMetaClass::_RESERVEDOSMetaClass1() 213 { panic(OSMetaClassPanicMsg, 1); } 214 void OSMetaClass::_RESERVEDOSMetaClass2() 215 { panic(OSMetaClassPanicMsg, 2); } 216 void OSMetaClass::_RESERVEDOSMetaClass3() 217 { panic(OSMetaClassPanicMsg, 3); } 218 void OSMetaClass::_RESERVEDOSMetaClass4() 219 { panic(OSMetaClassPanicMsg, 4); } 220 void OSMetaClass::_RESERVEDOSMetaClass5() 221 { panic(OSMetaClassPanicMsg, 5); } 222 void OSMetaClass::_RESERVEDOSMetaClass6() 223 { panic(OSMetaClassPanicMsg, 6); } 224 void OSMetaClass::_RESERVEDOSMetaClass7() 225 { panic(OSMetaClassPanicMsg, 7); } 226 227 void OSMetaClass::logError(OSReturn result) 228 { 229 const char *msg; 230 231 switch (result) { 232 case kOSMetaClassNoInit: 233 msg="OSMetaClass::preModLoad wasn't called, runtime internal error"; 234 break; 235 case kOSMetaClassNoDicts: 236 msg="Allocation failure for Metaclass internal dictionaries"; break; 237 case kOSMetaClassNoKModSet: 238 msg="Allocation failure for internal kmodule set"; break; 239 case kOSMetaClassNoInsKModSet: 240 msg="Can't insert the KMod set into the module dictionary"; break; 241 case kOSMetaClassDuplicateClass: 242 msg="Duplicate class"; break; 243 case kOSMetaClassNoSuper: 244 msg="Can't associate a class with its super class"; break; 245 case kOSMetaClassInstNoSuper: 246 msg="Instance construction, unknown super class."; break; 247 default: 248 case kOSMetaClassInternal: 249 msg="runtime internal error"; break; 250 case kOSReturnSuccess: 251 return; 252 } 253 printf("%s\n", msg); 254 } 255 256 OSMetaClass::OSMetaClass(const char *inClassName, 257 const OSMetaClass *inSuperClass, 258 unsigned int inClassSize) 259 { 260 instanceCount = 0; 261 classSize = inClassSize; 262 superClassLink = inSuperClass; 263 264 className = (const OSSymbol *) inClassName; 265 266 if (!sStalled) { 267 printf("OSMetaClass::preModLoad wasn't called for %s, " 268 "runtime internal error\n", inClassName); 269 } else if (!sStalled->result) { 270 // Grow stalled array if neccessary 271 if (sStalled->count >= sStalled->capacity) { 272 OSMetaClass **oldStalled = sStalled->classes; 273 int oldSize = sStalled->capacity * sizeof(OSMetaClass *); 274 int newSize = oldSize 275 + kKModCapacityIncrement * sizeof(OSMetaClass *); 276 277 sStalled->classes = (OSMetaClass **) kalloc(newSize); 278 if (!sStalled->classes) { 279 sStalled->classes = oldStalled; 280 sStalled->result = kOSMetaClassNoTempData; 281 return; 282 } 283 284 sStalled->capacity += kKModCapacityIncrement; 285 memmove(sStalled->classes, oldStalled, oldSize); 286 kfree(oldStalled, oldSize); 287 ACCUMSIZE(newSize - oldSize); 288 } 289 290 sStalled->classes[sStalled->count++] = this; 291 } 292 } 293 294 OSMetaClass::~OSMetaClass() 295 { 296 do { 297 OSCollectionIterator *iter; 298 299 if (sAllClassesDict) { 300 sAllClassesDict->removeObject(className); 301 className->release(); 302 } 303 304 iter = OSCollectionIterator::withCollection(sKModClassesDict); 305 if (!iter) 306 break; 307 308 OSSymbol *iterKey; 309 while ( (iterKey = (OSSymbol *) iter->getNextObject()) ) { 310 OSSet *kmodClassSet; 311 kmodClassSet = (OSSet *) sKModClassesDict->getObject(iterKey); 312 if (kmodClassSet && kmodClassSet->containsObject(this)) { 313 kmodClassSet->removeObject(this); 314 break; 315 } 316 } 317 iter->release(); 318 } while (false); 319 320 if (sStalled) { 321 unsigned int i; 322 323 // First pass find class in stalled list 324 for (i = 0; i < sStalled->count; i++) 325 if (this == sStalled->classes[i]) 326 break; 327 328 if (i < sStalled->count) { 329 sStalled->count--; 330 if (i < sStalled->count) 331 memmove(&sStalled->classes[i], &sStalled->classes[i+1], 332 (sStalled->count - i) * sizeof(OSMetaClass *)); 333 } 334 } 335 } 336 337 void *OSMetaClass::operator new(__unused size_t size) { return 0; } 338 void OSMetaClass::retain() const { } 339 void OSMetaClass::release() const { } 340 void OSMetaClass::release(__unused int when) const { } 341 void OSMetaClass::taggedRetain(__unused const void *tag) const { } 342 void OSMetaClass::taggedRelease(__unused const void *tag) const { } 343 void OSMetaClass::taggedRelease(__unused const void *tag, __unused const int when) const { } 344 int OSMetaClass::getRetainCount() const { return 0; } 345 346 const char *OSMetaClass::getClassName() const 347 { 348 return className->getCStringNoCopy(); 349 } 350 351 unsigned int OSMetaClass::getClassSize() const 352 { 353 return classSize; 354 } 355 356 void *OSMetaClass::preModLoad(const char *kmodName) 357 { 358 if (!loadLock) { 359 loadLock = mutex_alloc(0); 360 mutex_lock(loadLock); 361 } 362 else 363 mutex_lock(loadLock); 364 365 sStalled = (StalledData *) kalloc(sizeof(*sStalled)); 366 if (sStalled) { 367 sStalled->classes = (OSMetaClass **) 368 kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); 369 if (!sStalled->classes) { 370 kfree(sStalled, sizeof(*sStalled)); 371 return 0; 372 } 373 ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled)); 374 375 sStalled->result = kOSReturnSuccess; 376 sStalled->capacity = kKModCapacityIncrement; 377 sStalled->count = 0; 378 sStalled->kmodName = kmodName; 379 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 380 } 381 382 return sStalled; 383 } 384 385 bool OSMetaClass::checkModLoad(void *loadHandle) 386 { 387 return sStalled && loadHandle == sStalled 388 && sStalled->result == kOSReturnSuccess; 389 } 390 391 OSReturn OSMetaClass::postModLoad(void *loadHandle) 392 { 393 OSReturn result = kOSReturnSuccess; 394 OSSet *kmodSet = 0; 395 OSSymbol *myname = 0; 396 397 if (!sStalled || loadHandle != sStalled) { 398 logError(kOSMetaClassInternal); 399 return kOSMetaClassInternal; 400 } 401 402 if (sStalled->result) 403 result = sStalled->result; 404 else switch (sBootstrapState) { 405 case kNoDictionaries: 406 sBootstrapState = kMakingDictionaries; 407 // No break; fall through 408 409 case kMakingDictionaries: 410 sKModClassesDict = OSDictionary::withCapacity(kKModCapacityIncrement); 411 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 412 sSortedByClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 413 if (!sAllClassesDict || !sKModClassesDict || !sSortedByClassesDict) { 414 result = kOSMetaClassNoDicts; 415 break; 416 } 417 // No break; fall through 418 419 case kCompletedBootstrap: 420 { 421 unsigned int i; 422 myname = (OSSymbol *)OSSymbol::withCStringNoCopy(sStalled->kmodName); 423 424 if (!sStalled->count) 425 break; // Nothing to do so just get out 426 427 // First pass checking classes aren't already loaded 428 for (i = 0; i < sStalled->count; i++) { 429 OSMetaClass *me = sStalled->classes[i]; 430 431 if (0 != sAllClassesDict->getObject((const char *) me->className)) { 432 printf("Class \"%s\" is duplicate\n", (const char *) me->className); 433 result = kOSMetaClassDuplicateClass; 434 break; 435 } 436 } 437 if (i != sStalled->count) 438 break; 439 440 kmodSet = OSSet::withCapacity(sStalled->count); 441 if (!kmodSet) { 442 result = kOSMetaClassNoKModSet; 443 break; 444 } 445 446 if (!sKModClassesDict->setObject(myname, kmodSet)) { 447 result = kOSMetaClassNoInsKModSet; 448 break; 449 } 450 451 // Second pass symbolling strings and inserting classes in dictionary 452 for (i = 0; i < sStalled->count; i++) { 453 OSMetaClass *me = sStalled->classes[i]; 454 me->className = 455 OSSymbol::withCStringNoCopy((const char *) me->className); 456 457 sAllClassesDict->setObject(me->className, me); 458 kmodSet->setObject(me); 459 sSortedByClassesDict->setObject((const OSSymbol *)me, myname); 460 } 461 sBootstrapState = kCompletedBootstrap; 462 break; 463 } 464 465 default: 466 result = kOSMetaClassInternal; 467 break; 468 } 469 470 if (kmodSet) 471 kmodSet->release(); 472 473 if (myname) 474 myname->release(); 475 476 if (sStalled) { 477 ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) 478 + sizeof(*sStalled))); 479 kfree(sStalled->classes, 480 sStalled->capacity * sizeof(OSMetaClass *)); 481 kfree(sStalled, sizeof(*sStalled)); 482 sStalled = 0; 483 } 484 485 logError(result); 486 mutex_unlock(loadLock); 487 return result; 488 } 489 490 491 void OSMetaClass::instanceConstructed() const 492 { 493 // if ((0 == OSIncrementAtomic((SInt32 *)&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 494 if ((0 == OSIncrementAtomic((SInt32 *) &instanceCount)) && superClassLink) 495 superClassLink->instanceConstructed(); 496 } 497 498 void OSMetaClass::instanceDestructed() const 499 { 500 if ((1 == OSDecrementAtomic((SInt32 *) &instanceCount)) && superClassLink) 501 superClassLink->instanceDestructed(); 502 503 if( ((int) instanceCount) < 0) 504 printf("%s: bad retain(%d)", getClassName(), instanceCount); 505 } 506 507 bool OSMetaClass::modHasInstance(const char *kmodName) 508 { 509 bool result = false; 510 511 if (!loadLock) { 512 loadLock = mutex_alloc(0); 513 mutex_lock(loadLock); 514 } 515 else 516 mutex_lock(loadLock); 517 518 do { 519 OSSet *kmodClasses; 520 OSCollectionIterator *iter; 521 OSMetaClass *checkClass; 522 523 kmodClasses = OSDynamicCast(OSSet, 524 sKModClassesDict->getObject(kmodName)); 525 if (!kmodClasses) 526 break; 527 528 iter = OSCollectionIterator::withCollection(kmodClasses); 529 if (!iter) 530 break; 531 532 while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) 533 if (checkClass->getInstanceCount()) { 534 result = true; 535 break; 536 } 537 538 iter->release(); 539 } while (false); 540 541 mutex_unlock(loadLock); 542 543 return result; 544 } 545 546 void OSMetaClass::reportModInstances(const char *kmodName) 547 { 548 OSSet *kmodClasses; 549 OSCollectionIterator *iter; 550 OSMetaClass *checkClass; 551 552 kmodClasses = OSDynamicCast(OSSet, 553 sKModClassesDict->getObject(kmodName)); 554 if (!kmodClasses) 555 return; 556 557 iter = OSCollectionIterator::withCollection(kmodClasses); 558 if (!iter) 559 return; 560 561 while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) 562 if (checkClass->getInstanceCount()) { 563 printf("%s: %s has %d instance(s)\n", 564 kmodName, 565 checkClass->getClassName(), 566 checkClass->getInstanceCount()); 567 } 568 569 iter->release(); 570 } 571 572 573 extern "C" { 574 575 IOReturn OSMetaClassSystemSleepOrWake(UInt32 messageType) 576 { 577 mutex_lock(loadLock); 578 579 /* If the system is going to sleep, cancel the reaper thread timer 580 * and mark unloads disabled in case it just fired but hasn't 581 * taken the lock yet. If we are coming back from sleep, just 582 * set unloads enabled; IOService's normal operation will cause 583 * unloads to be considered soon enough. 584 */ 585 if (messageType == kIOMessageSystemWillSleep) { 586 if (unloadCallout) { 587 thread_call_cancel(unloadCallout); 588 } 589 unloadsEnabled = false; 590 } else if (messageType == kIOMessageSystemHasPoweredOn) { 591 unloadsEnabled = true; 592 } 593 mutex_unlock(loadLock); 594 595 return kIOReturnSuccess; 596 } 597 598 }; 599 600 extern "C" kern_return_t kmod_unload_cache(void); 601 602 static void _OSMetaClassConsiderUnloads(__unused thread_call_param_t p0, 603 __unused thread_call_param_t p1) 604 { 605 OSSet *kmodClasses; 606 OSSymbol *kmodName; 607 OSCollectionIterator *kmods; 608 OSCollectionIterator *classes; 609 OSMetaClass *checkClass; 610 kmod_info_t *ki = 0; 611 kern_return_t ret; 612 bool didUnload; 613 614 mutex_lock(loadLock); 615 616 if (!unloadsEnabled) { 617 mutex_unlock(loadLock); 618 return; 619 } 620 621 do { 622 623 kmods = OSCollectionIterator::withCollection(sKModClassesDict); 624 if (!kmods) 625 break; 626 627 didUnload = false; 628 while ( (kmodName = (OSSymbol *) kmods->getNextObject()) ) { 629 630 if (ki) { 631 kfree(ki, sizeof(kmod_info_t)); 632 ki = 0; 633 } 634 635 ki = kmod_lookupbyname_locked((char *)kmodName->getCStringNoCopy()); 636 if (!ki) 637 continue; 638 639 if (ki->reference_count) { 640 continue; 641 } 642 643 kmodClasses = OSDynamicCast(OSSet, 644 sKModClassesDict->getObject(kmodName)); 645 classes = OSCollectionIterator::withCollection(kmodClasses); 646 if (!classes) 647 continue; 648 649 while ((checkClass = (OSMetaClass *) classes->getNextObject()) 650 && (0 == checkClass->getInstanceCount())) 651 {} 652 classes->release(); 653 654 if (0 == checkClass) { 655 OSRuntimeUnloadCPP(ki, 0); // call destructors 656 ret = kmod_destroy(host_priv_self(), ki->id); 657 didUnload = true; 658 } 659 660 } 661 662 kmods->release(); 663 664 } while (didUnload); 665 666 mutex_unlock(loadLock); 667 668 kmod_unload_cache(); 669 } 670 671 void OSMetaClass::considerUnloads() 672 { 673 AbsoluteTime when; 674 675 mutex_lock(loadLock); 676 677 if (!unloadCallout) 678 unloadCallout = thread_call_allocate(&_OSMetaClassConsiderUnloads, 0); 679 680 thread_call_cancel(unloadCallout); 681 clock_interval_to_deadline(sConsiderUnloadDelay, 1000 * 1000 * 1000, &when); 682 thread_call_enter_delayed(unloadCallout, when); 683 684 mutex_unlock(loadLock); 685 } 686 687 const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSSymbol *name) 688 { 689 OSMetaClass *retMeta = 0; 690 691 if (!name) 692 return 0; 693 694 if (sAllClassesDict) 695 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 696 697 if (!retMeta && sStalled) 698 { 699 // Oh dear we have to scan the stalled list and walk the 700 // the stalled list manually. 701 const char *cName = name->getCStringNoCopy(); 702 unsigned int i; 703 704 // find class in stalled list 705 for (i = 0; i < sStalled->count; i++) { 706 retMeta = sStalled->classes[i]; 707 if (0 == strcmp(cName, (const char *) retMeta->className)) 708 break; 709 } 710 711 if (i < sStalled->count) 712 retMeta = 0; 713 } 714 715 return retMeta; 716 } 717 718 OSObject *OSMetaClass::allocClassWithName(const OSSymbol *name) 719 { 720 OSObject * result; 721 mutex_lock(loadLock); 722 723 const OSMetaClass * const meta = getMetaClassWithName(name); 724 725 if (meta) 726 result = meta->alloc(); 727 else 728 result = 0; 729 730 mutex_unlock(loadLock); 731 732 return result; 733 } 734 735 OSObject *OSMetaClass::allocClassWithName(const OSString *name) 736 { 737 const OSSymbol *tmpKey = OSSymbol::withString(name); 738 OSObject *result = allocClassWithName(tmpKey); 739 tmpKey->release(); 740 return result; 741 } 742 743 OSObject *OSMetaClass::allocClassWithName(const char *name) 744 { 745 const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name); 746 OSObject *result = allocClassWithName(tmpKey); 747 tmpKey->release(); 748 return result; 749 } 750 751 752 OSMetaClassBase *OSMetaClass:: 753 checkMetaCastWithName(const OSSymbol *name, const OSMetaClassBase *in) 754 { 755 OSMetaClassBase * result; 756 mutex_lock(loadLock); 757 const OSMetaClass * const meta = getMetaClassWithName(name); 758 759 if (meta) 760 result = meta->checkMetaCast(in); 761 else 762 result = 0; 763 764 mutex_unlock(loadLock); 765 return result; 766 } 767 768 OSMetaClassBase *OSMetaClass:: 769 checkMetaCastWithName(const OSString *name, const OSMetaClassBase *in) 770 { 771 const OSSymbol *tmpKey = OSSymbol::withString(name); 772 OSMetaClassBase *result = checkMetaCastWithName(tmpKey, in); 773 tmpKey->release(); 774 return result; 775 } 776 777 OSMetaClassBase *OSMetaClass:: 778 checkMetaCastWithName(const char *name, const OSMetaClassBase *in) 779 { 780 const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name); 781 OSMetaClassBase *result = checkMetaCastWithName(tmpKey, in); 782 tmpKey->release(); 783 return result; 784 } 785 786 /* 787 OSMetaClass::checkMetaCast 788 checkMetaCast(const OSMetaClassBase *check) 789 790 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. 791 792 Generally this method is not invoked directly but is used to implement the OSMetaClassBase::metaCast member function. 793 794 See also OSMetaClassBase::metaCast 795 796 */ 797 OSMetaClassBase *OSMetaClass::checkMetaCast(const OSMetaClassBase *check) const 798 { 799 const OSMetaClass * const toMeta = this; 800 const OSMetaClass *fromMeta; 801 802 for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) { 803 if (toMeta == fromMeta) 804 return (OSMetaClassBase *) check; // Discard const 805 806 if (!fromMeta->superClassLink) 807 break; 808 } 809 810 return 0; 811 } 812 813 void OSMetaClass::reservedCalled(int ind) const 814 { 815 const char *cname = className->getCStringNoCopy(); 816 panic("%s::_RESERVED%s%d called\n", cname, cname, ind); 817 } 818 819 const OSMetaClass *OSMetaClass::getSuperClass() const 820 { 821 return superClassLink; 822 } 823 824 const OSSymbol *OSMetaClass::getKmodName() const 825 { 826 return (const OSSymbol *)sSortedByClassesDict->getObject((OSSymbol *)this); 827 } 828 829 unsigned int OSMetaClass::getInstanceCount() const 830 { 831 return instanceCount; 832 } 833 834 void OSMetaClass::printInstanceCounts() 835 { 836 OSCollectionIterator *classes; 837 OSSymbol *className; 838 OSMetaClass *meta; 839 840 classes = OSCollectionIterator::withCollection(sAllClassesDict); 841 if (!classes) 842 return; 843 844 while( (className = (OSSymbol *)classes->getNextObject())) { 845 meta = (OSMetaClass *) sAllClassesDict->getObject(className); 846 assert(meta); 847 848 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 849 className->getCStringNoCopy(), 850 meta->getInstanceCount(), 851 meta->getClassSize(), 852 meta->getInstanceCount() * meta->getClassSize() ); 853 } 854 printf("\n"); 855 classes->release(); 856 } 857 858 OSDictionary * OSMetaClass::getClassDictionary() 859 { 860 panic("OSMetaClass::getClassDictionary(): Obsoleted\n"); 861 return 0; 862 } 863 864 bool OSMetaClass::serialize(__unused OSSerialize *s) const 865 { 866 panic("OSMetaClass::serialize(): Obsoleted\n"); 867 return false; 868 } 869 870 void OSMetaClass::serializeClassDictionary(OSDictionary *serializeDictionary) 871 { 872 OSDictionary *classDict; 873 874 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount()); 875 if (!classDict) 876 return; 877 878 mutex_lock(loadLock); 879 do { 880 OSCollectionIterator *classes; 881 const OSSymbol *className; 882 883 classes = OSCollectionIterator::withCollection(sAllClassesDict); 884 if (!classes) 885 break; 886 887 while ((className = (const OSSymbol *) classes->getNextObject())) { 888 const OSMetaClass *meta; 889 OSNumber *count; 890 891 meta = (OSMetaClass *) sAllClassesDict->getObject(className); 892 count = OSNumber::withNumber(meta->getInstanceCount(), 32); 893 if (count) { 894 classDict->setObject(className, count); 895 count->release(); 896 } 897 } 898 classes->release(); 899 900 serializeDictionary->setObject("Classes", classDict); 901 } while (0); 902 903 mutex_unlock(loadLock); 904 905 classDict->release(); 906 } 907