xref: /xnu-11215/libkern/c++/OSMetaClass.cpp (revision c1dac77f)
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