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