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