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