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