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