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