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