]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSMetaClass.cpp
4c5a81f39fa8ab5fdaa56b03609dbcf32c5ef968
[apple/xnu.git] / libkern / c++ / OSMetaClass.cpp
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