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