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 <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; 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 void OSMetaClassBase::_RESERVEDOSMetaClassBase0() 88 { panic(OSMetaClassBasePanicMsg, 0); } 89 void OSMetaClassBase::_RESERVEDOSMetaClassBase1() 90 { panic(OSMetaClassBasePanicMsg, 1); } 91 void OSMetaClassBase::_RESERVEDOSMetaClassBase2() 92 { panic(OSMetaClassBasePanicMsg, 2); } 93 void OSMetaClassBase::_RESERVEDOSMetaClassBase3() 94 { panic(OSMetaClassBasePanicMsg, 3); } 95 void OSMetaClassBase::_RESERVEDOSMetaClassBase4() 96 { panic(OSMetaClassBasePanicMsg, 4); } 97 void OSMetaClassBase::_RESERVEDOSMetaClassBase5() 98 { panic(OSMetaClassBasePanicMsg, 5); } 99 void OSMetaClassBase::_RESERVEDOSMetaClassBase6() 100 { panic(OSMetaClassBasePanicMsg, 6); } 101 void OSMetaClassBase::_RESERVEDOSMetaClassBase7() 102 { panic(OSMetaClassBasePanicMsg, 7); } 103 104 OSMetaClassBase::OSMetaClassBase() 105 { 106 } 107 108 OSMetaClassBase::~OSMetaClassBase() 109 { 110 void **thisVTable; 111 112 thisVTable = (void **) this; 113 *thisVTable = (void *) -1UL; 114 } 115 116 bool OSMetaClassBase::isEqualTo(const OSMetaClassBase *anObj) const 117 { 118 return this == anObj; 119 } 120 121 OSMetaClassBase *OSMetaClassBase::metaCast(const OSMetaClass *toMeta) const 122 { 123 return toMeta->checkMetaCast(this); 124 } 125 126 OSMetaClassBase *OSMetaClassBase::metaCast(const OSSymbol *toMetaSymb) const 127 { 128 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this); 129 } 130 131 OSMetaClassBase *OSMetaClassBase::metaCast(const OSString *toMetaStr) const 132 { 133 const OSSymbol *tempSymb = OSSymbol::withString(toMetaStr); 134 OSMetaClassBase *ret = 0; 135 if (tempSymb) { 136 ret = metaCast(tempSymb); 137 tempSymb->release(); 138 } 139 return ret; 140 } 141 142 OSMetaClassBase *OSMetaClassBase::metaCast(const char *toMetaCStr) const 143 { 144 const OSSymbol *tempSymb = OSSymbol::withCStringNoCopy(toMetaCStr); 145 OSMetaClassBase *ret = 0; 146 if (tempSymb) { 147 ret = metaCast(tempSymb); 148 tempSymb->release(); 149 } 150 return ret; 151 } 152 153 class OSMetaClassMeta : public OSMetaClass 154 { 155 public: 156 OSMetaClassMeta(); 157 OSObject *alloc() const; 158 }; 159 OSMetaClassMeta::OSMetaClassMeta() 160 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass)) 161 { } 162 OSObject *OSMetaClassMeta::alloc() const { return 0; } 163 164 static OSMetaClassMeta sOSMetaClassMeta; 165 166 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta; 167 const OSMetaClass * OSMetaClass::getMetaClass() const 168 { return &sOSMetaClassMeta; } 169 170 static const char OSMetaClassPanicMsg[] = 171 "OSMetaClass::_RESERVEDOSMetaClass%d called\n"; 172 173 void OSMetaClass::_RESERVEDOSMetaClass0() 174 { panic(OSMetaClassPanicMsg, 0); } 175 void OSMetaClass::_RESERVEDOSMetaClass1() 176 { panic(OSMetaClassPanicMsg, 1); } 177 void OSMetaClass::_RESERVEDOSMetaClass2() 178 { panic(OSMetaClassPanicMsg, 2); } 179 void OSMetaClass::_RESERVEDOSMetaClass3() 180 { panic(OSMetaClassPanicMsg, 3); } 181 void OSMetaClass::_RESERVEDOSMetaClass4() 182 { panic(OSMetaClassPanicMsg, 4); } 183 void OSMetaClass::_RESERVEDOSMetaClass5() 184 { panic(OSMetaClassPanicMsg, 5); } 185 void OSMetaClass::_RESERVEDOSMetaClass6() 186 { panic(OSMetaClassPanicMsg, 6); } 187 void OSMetaClass::_RESERVEDOSMetaClass7() 188 { panic(OSMetaClassPanicMsg, 7); } 189 190 void OSMetaClass::logError(OSReturn result) 191 { 192 const char *msg; 193 194 switch (result) { 195 case kOSMetaClassNoInit: 196 msg="OSMetaClass::preModLoad wasn't called, runtime internal error"; 197 break; 198 case kOSMetaClassNoDicts: 199 msg="Allocation failure for Metaclass internal dictionaries"; break; 200 case kOSMetaClassNoKModSet: 201 msg="Allocation failure for internal kmodule set"; break; 202 case kOSMetaClassNoInsKModSet: 203 msg="Can't insert the KMod set into the module dictionary"; break; 204 case kOSMetaClassDuplicateClass: 205 msg="Duplicate class"; break; 206 case kOSMetaClassNoSuper: 207 msg="Can't associate a class with its super class"; break; 208 case kOSMetaClassInstNoSuper: 209 msg="Instance construction, unknown super class."; break; 210 default: 211 case kOSMetaClassInternal: 212 msg="runtime internal error"; break; 213 case kOSReturnSuccess: 214 return; 215 } 216 printf("%s\n", msg); 217 } 218 219 OSMetaClass::OSMetaClass(const char *inClassName, 220 const OSMetaClass *inSuperClass, 221 unsigned int inClassSize) 222 { 223 instanceCount = 0; 224 classSize = inClassSize; 225 superClassLink = inSuperClass; 226 227 className = (const OSSymbol *) inClassName; 228 229 if (!sStalled) { 230 printf("OSMetaClass::preModLoad wasn't called for %s, " 231 "runtime internal error\n", inClassName); 232 } else if (!sStalled->result) { 233 // Grow stalled array if neccessary 234 if (sStalled->count >= sStalled->capacity) { 235 OSMetaClass **oldStalled = sStalled->classes; 236 int oldSize = sStalled->capacity * sizeof(OSMetaClass *); 237 int newSize = oldSize 238 + kKModCapacityIncrement * sizeof(OSMetaClass *); 239 240 sStalled->classes = (OSMetaClass **) kalloc(newSize); 241 if (!sStalled->classes) { 242 sStalled->classes = oldStalled; 243 sStalled->result = kOSMetaClassNoTempData; 244 return; 245 } 246 247 sStalled->capacity += kKModCapacityIncrement; 248 memmove(sStalled->classes, oldStalled, oldSize); 249 kfree((vm_offset_t)oldStalled, oldSize); 250 ACCUMSIZE(newSize - oldSize); 251 } 252 253 sStalled->classes[sStalled->count++] = this; 254 } 255 } 256 257 OSMetaClass::~OSMetaClass() 258 { 259 do { 260 OSCollectionIterator *iter; 261 262 if (sAllClassesDict) 263 sAllClassesDict->removeObject(className); 264 265 iter = OSCollectionIterator::withCollection(sKModClassesDict); 266 if (!iter) 267 break; 268 269 OSSymbol *iterKey; 270 while ( (iterKey = (OSSymbol *) iter->getNextObject()) ) { 271 OSSet *kmodClassSet; 272 kmodClassSet = (OSSet *) sKModClassesDict->getObject(iterKey); 273 if (kmodClassSet && kmodClassSet->containsObject(this)) { 274 kmodClassSet->removeObject(this); 275 break; 276 } 277 } 278 iter->release(); 279 } while (false); 280 281 if (sStalled) { 282 unsigned int i; 283 284 // First pass find class in stalled list 285 for (i = 0; i < sStalled->count; i++) 286 if (this == sStalled->classes[i]) 287 break; 288 289 if (i < sStalled->count) { 290 sStalled->count--; 291 if (i < sStalled->count) 292 memmove(&sStalled->classes[i], &sStalled->classes[i+1], 293 (sStalled->count - i) * sizeof(OSMetaClass *)); 294 } 295 return; 296 } 297 } 298 299 // Don't do anything as these classes must be statically allocated 300 void *OSMetaClass::operator new(size_t size) { return 0; } 301 void OSMetaClass::operator delete(void *mem, size_t size) { } 302 void OSMetaClass::retain() const { } 303 void OSMetaClass::release() const { } 304 void OSMetaClass::release(int when) const { }; 305 int OSMetaClass::getRetainCount() const { return 0; } 306 307 const char *OSMetaClass::getClassName() const 308 { 309 return className->getCStringNoCopy(); 310 } 311 312 unsigned int OSMetaClass::getClassSize() const 313 { 314 return classSize; 315 } 316 317 void *OSMetaClass::preModLoad(const char *kmodName) 318 { 319 if (!loadLock) { 320 loadLock = mutex_alloc(ETAP_IO_AHA); 321 _mutex_lock(loadLock); 322 } 323 else 324 _mutex_lock(loadLock); 325 326 sStalled = (StalledData *) kalloc(sizeof(*sStalled)); 327 if (sStalled) { 328 sStalled->classes = (OSMetaClass **) 329 kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); 330 if (!sStalled->classes) { 331 kfree((vm_offset_t) sStalled, sizeof(*sStalled)); 332 return 0; 333 } 334 ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled)); 335 336 sStalled->result = kOSReturnSuccess; 337 sStalled->capacity = kKModCapacityIncrement; 338 sStalled->count = 0; 339 sStalled->kmodName = kmodName; 340 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 341 } 342 343 return sStalled; 344 } 345 346 bool OSMetaClass::checkModLoad(void *loadHandle) 347 { 348 return sStalled && loadHandle == sStalled 349 && sStalled->result == kOSReturnSuccess; 350 } 351 352 OSReturn OSMetaClass::postModLoad(void *loadHandle) 353 { 354 OSReturn result = kOSReturnSuccess; 355 OSSet *kmodSet = 0; 356 357 if (!sStalled || loadHandle != sStalled) { 358 logError(kOSMetaClassInternal); 359 return kOSMetaClassInternal; 360 } 361 362 if (sStalled->result) 363 result = sStalled->result; 364 else switch (sBootstrapState) { 365 case kNoDictionaries: 366 sBootstrapState = kMakingDictionaries; 367 // No break; fall through 368 369 case kMakingDictionaries: 370 sKModClassesDict = OSDictionary::withCapacity(kKModCapacityIncrement); 371 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 372 if (!sAllClassesDict || !sKModClassesDict) { 373 result = kOSMetaClassNoDicts; 374 break; 375 } 376 // No break; fall through 377 378 case kCompletedBootstrap: 379 { 380 unsigned int i; 381 382 if (!sStalled->count) 383 break; // Nothing to do so just get out 384 385 // First pass checking classes aren't already loaded 386 for (i = 0; i < sStalled->count; i++) { 387 OSMetaClass *me = sStalled->classes[i]; 388 389 if (0 != sAllClassesDict->getObject((const char *) me->className)) { 390 printf("Class \"%s\" is duplicate\n", (const char *) me->className); 391 result = kOSMetaClassDuplicateClass; 392 break; 393 } 394 } 395 if (i != sStalled->count) 396 break; 397 398 kmodSet = OSSet::withCapacity(sStalled->count); 399 if (!kmodSet) { 400 result = kOSMetaClassNoKModSet; 401 break; 402 } 403 404 if (!sKModClassesDict->setObject(sStalled->kmodName, kmodSet)) { 405 result = kOSMetaClassNoInsKModSet; 406 break; 407 } 408 409 // Second pass symbolling strings and inserting classes in dictionary 410 for (unsigned int i = 0; i < sStalled->count; i++) { 411 OSMetaClass *me = sStalled->classes[i]; 412 me->className = 413 OSSymbol::withCStringNoCopy((const char *) me->className); 414 415 sAllClassesDict->setObject(me->className, me); 416 kmodSet->setObject(me); 417 } 418 sBootstrapState = kCompletedBootstrap; 419 break; 420 } 421 422 default: 423 result = kOSMetaClassInternal; 424 break; 425 } 426 427 if (kmodSet) 428 kmodSet->release(); 429 430 if (sStalled) { 431 ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) 432 + sizeof(*sStalled))); 433 kfree((vm_offset_t) sStalled->classes, 434 sStalled->capacity * sizeof(OSMetaClass *)); 435 kfree((vm_offset_t) sStalled, sizeof(*sStalled)); 436 sStalled = 0; 437 } 438 439 logError(result); 440 mutex_unlock(loadLock); 441 return result; 442 } 443 444 445 void OSMetaClass::instanceConstructed() const 446 { 447 // if ((0 == OSIncrementAtomic((SInt32 *)&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 448 if ((0 == OSIncrementAtomic((SInt32 *) &instanceCount)) && superClassLink) 449 superClassLink->instanceConstructed(); 450 } 451 452 void OSMetaClass::instanceDestructed() const 453 { 454 if ((1 == OSDecrementAtomic((SInt32 *) &instanceCount)) && superClassLink) 455 superClassLink->instanceDestructed(); 456 457 if( ((int) instanceCount) < 0) 458 printf("%s: bad retain(%d)", getClassName(), instanceCount); 459 } 460 461 bool OSMetaClass::modHasInstance(const char *kmodName) 462 { 463 bool result = false; 464 465 if (!loadLock) { 466 loadLock = mutex_alloc(ETAP_IO_AHA); 467 _mutex_lock(loadLock); 468 } 469 else 470 _mutex_lock(loadLock); 471 472 do { 473 OSSet *kmodClasses; 474 OSCollectionIterator *iter; 475 OSMetaClass *checkClass; 476 477 kmodClasses = OSDynamicCast(OSSet, 478 sKModClassesDict->getObject(kmodName)); 479 if (!kmodClasses) 480 break; 481 482 iter = OSCollectionIterator::withCollection(kmodClasses); 483 if (!iter) 484 break; 485 486 while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) 487 if (checkClass->getInstanceCount()) { 488 result = true; 489 break; 490 } 491 492 iter->release(); 493 } while (false); 494 495 mutex_unlock(loadLock); 496 497 return result; 498 } 499 500 void OSMetaClass::reportModInstances(const char *kmodName) 501 { 502 OSSet *kmodClasses; 503 OSCollectionIterator *iter; 504 OSMetaClass *checkClass; 505 506 kmodClasses = OSDynamicCast(OSSet, 507 sKModClassesDict->getObject(kmodName)); 508 if (!kmodClasses) 509 return; 510 511 iter = OSCollectionIterator::withCollection(kmodClasses); 512 if (!iter) 513 return; 514 515 while ( (checkClass = (OSMetaClass *) iter->getNextObject()) ) 516 if (checkClass->getInstanceCount()) { 517 printf("%s: %s has %d instance(s)\n", 518 kmodName, 519 checkClass->getClassName(), 520 checkClass->getInstanceCount()); 521 } 522 523 iter->release(); 524 } 525 526 static void _OSMetaClassConsiderUnloads(thread_call_param_t p0, 527 thread_call_param_t p1) 528 { 529 OSSet *kmodClasses; 530 OSSymbol *kmodName; 531 OSCollectionIterator *kmods; 532 OSCollectionIterator *classes; 533 OSMetaClass *checkClass; 534 kmod_info_t *ki; 535 kern_return_t ret; 536 bool didUnload; 537 538 _mutex_lock(loadLock); 539 540 do { 541 542 kmods = OSCollectionIterator::withCollection(sKModClassesDict); 543 if (!kmods) 544 break; 545 546 didUnload = false; 547 while ( (kmodName = (OSSymbol *) kmods->getNextObject()) ) { 548 549 ki = kmod_lookupbyname((char *)kmodName->getCStringNoCopy()); 550 if (!ki) 551 continue; 552 553 if (ki->reference_count) 554 continue; 555 556 kmodClasses = OSDynamicCast(OSSet, 557 sKModClassesDict->getObject(kmodName)); 558 classes = OSCollectionIterator::withCollection(kmodClasses); 559 if (!classes) 560 continue; 561 562 while ((checkClass = (OSMetaClass *) classes->getNextObject()) 563 && (0 == checkClass->getInstanceCount())) 564 {} 565 classes->release(); 566 567 if (0 == checkClass) { 568 OSRuntimeUnloadCPP(ki, 0); // call destructors 569 ret = kmod_destroy(host_priv_self(), ki->id); 570 didUnload = true; 571 } 572 573 } while (false); 574 575 kmods->release(); 576 577 } while (didUnload); 578 579 mutex_unlock(loadLock); 580 } 581 582 void OSMetaClass::considerUnloads() 583 { 584 static thread_call_t unloadCallout; 585 AbsoluteTime when; 586 587 _mutex_lock(loadLock); 588 589 if (!unloadCallout) 590 unloadCallout = thread_call_allocate(&_OSMetaClassConsiderUnloads, 0); 591 592 thread_call_cancel(unloadCallout); 593 clock_interval_to_deadline(sConsiderUnloadDelay, 1000 * 1000 * 1000, &when); 594 thread_call_enter_delayed(unloadCallout, when); 595 596 mutex_unlock(loadLock); 597 } 598 599 const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSSymbol *name) 600 { 601 OSMetaClass *retMeta = 0; 602 603 if (!name) 604 return 0; 605 606 if (sAllClassesDict) 607 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 608 609 if (!retMeta && sStalled) 610 { 611 // Oh dear we have to scan the stalled list and walk the 612 // the stalled list manually. 613 const char *cName = name->getCStringNoCopy(); 614 unsigned int i; 615 616 // find class in stalled list 617 for (i = 0; i < sStalled->count; i++) { 618 retMeta = sStalled->classes[i]; 619 if (0 == strcmp(cName, (const char *) retMeta->className)) 620 break; 621 } 622 623 if (i < sStalled->count) 624 retMeta = 0; 625 } 626 627 return retMeta; 628 } 629 630 OSObject *OSMetaClass::allocClassWithName(const OSSymbol *name) 631 { 632 OSObject * result; 633 _mutex_lock(loadLock); 634 635 const OSMetaClass * const meta = getMetaClassWithName(name); 636 637 if (meta) 638 result = meta->alloc(); 639 else 640 result = 0; 641 642 mutex_unlock(loadLock); 643 644 return result; 645 } 646 647 OSObject *OSMetaClass::allocClassWithName(const OSString *name) 648 { 649 const OSSymbol *tmpKey = OSSymbol::withString(name); 650 OSObject *result = allocClassWithName(tmpKey); 651 tmpKey->release(); 652 return result; 653 } 654 655 OSObject *OSMetaClass::allocClassWithName(const char *name) 656 { 657 const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name); 658 OSObject *result = allocClassWithName(tmpKey); 659 tmpKey->release(); 660 return result; 661 } 662 663 664 OSMetaClassBase *OSMetaClass:: 665 checkMetaCastWithName(const OSSymbol *name, const OSMetaClassBase *in) 666 { 667 OSMetaClassBase * result; 668 _mutex_lock(loadLock); 669 const OSMetaClass * const meta = getMetaClassWithName(name); 670 671 if (meta) 672 result = meta->checkMetaCast(in); 673 else 674 result = 0; 675 676 mutex_unlock(loadLock); 677 return result; 678 } 679 680 OSMetaClassBase *OSMetaClass:: 681 checkMetaCastWithName(const OSString *name, const OSMetaClassBase *in) 682 { 683 const OSSymbol *tmpKey = OSSymbol::withString(name); 684 OSMetaClassBase *result = checkMetaCastWithName(tmpKey, in); 685 tmpKey->release(); 686 return result; 687 } 688 689 OSMetaClassBase *OSMetaClass:: 690 checkMetaCastWithName(const char *name, const OSMetaClassBase *in) 691 { 692 const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name); 693 OSMetaClassBase *result = checkMetaCastWithName(tmpKey, in); 694 tmpKey->release(); 695 return result; 696 } 697 698 /* 699 OSMetaClass::checkMetaCast 700 checkMetaCast(const OSMetaClassBase *check) 701 702 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. 703 704 Generally this method is not invoked directly but is used to implement the OSMetaClassBase::metaCast member function. 705 706 See also OSMetaClassBase::metaCast 707 708 */ 709 OSMetaClassBase *OSMetaClass::checkMetaCast(const OSMetaClassBase *check) const 710 { 711 const OSMetaClass * const toMeta = this; 712 const OSMetaClass *fromMeta; 713 714 for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) { 715 if (toMeta == fromMeta) 716 return (OSMetaClassBase *) check; // Discard const 717 718 if (!fromMeta->superClassLink) 719 break; 720 } 721 722 return 0; 723 } 724 725 void OSMetaClass::reservedCalled(int ind) const 726 { 727 const char *cname = className->getCStringNoCopy(); 728 panic("%s::_RESERVED%s%d called\n", cname, cname, ind); 729 } 730 731 const OSMetaClass *OSMetaClass::getSuperClass() const 732 { 733 return superClassLink; 734 } 735 736 unsigned int OSMetaClass::getInstanceCount() const 737 { 738 return instanceCount; 739 } 740 741 void OSMetaClass::printInstanceCounts() 742 { 743 OSCollectionIterator *classes; 744 OSSymbol *className; 745 OSMetaClass *meta; 746 747 classes = OSCollectionIterator::withCollection(sAllClassesDict); 748 if (!classes) 749 return; 750 751 while( (className = (OSSymbol *)classes->getNextObject())) { 752 meta = (OSMetaClass *) sAllClassesDict->getObject(className); 753 assert(meta); 754 755 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 756 className->getCStringNoCopy(), 757 meta->getInstanceCount(), 758 meta->getClassSize(), 759 meta->getInstanceCount() * meta->getClassSize() ); 760 } 761 printf("\n"); 762 classes->release(); 763 } 764 765 OSDictionary * OSMetaClass::getClassDictionary() 766 { 767 return sAllClassesDict; 768 } 769 770 bool OSMetaClass::serialize(OSSerialize *s) const 771 { 772 OSDictionary * dict; 773 OSNumber * off; 774 bool ok = false; 775 776 if (s->previouslySerialized(this)) return true; 777 778 dict = 0;// IODictionary::withCapacity(2); 779 off = OSNumber::withNumber(getInstanceCount(), 32); 780 781 if (dict) { 782 dict->setObject("InstanceCount", off ); 783 ok = dict->serialize(s); 784 } else if( off) 785 ok = off->serialize(s); 786 787 if (dict) 788 dict->release(); 789 if (off) 790 off->release(); 791 792 return ok; 793 } 794 795