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