2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* OSMetaClass.cpp created by gvdl on Fri 1998-11-17 */
32 #include <libkern/OSReturn.h>
34 #include <libkern/c++/OSMetaClass.h>
35 #include <libkern/c++/OSObject.h>
36 #include <libkern/c++/OSKext.h>
38 #include <libkern/c++/OSCollectionIterator.h>
39 #include <libkern/c++/OSDictionary.h>
40 #include <libkern/c++/OSArray.h>
41 #include <libkern/c++/OSSet.h>
42 #include <libkern/c++/OSSymbol.h>
43 #include <libkern/c++/OSNumber.h>
44 #include <libkern/c++/OSSerialize.h>
46 #include <libkern/c++/OSLib.h>
47 #include <libkern/OSAtomic.h>
49 #include <IOKit/IOLib.h>
51 #include <IOKit/IOKitDebug.h>
56 #include <sys/systm.h>
57 #include <mach/mach_types.h>
58 #include <kern/locks.h>
59 #include <kern/clock.h>
60 #include <kern/thread_call.h>
61 #include <kern/host.h>
62 #include <mach/mach_interface.h>
66 #endif /* PRAGMA_MARK */
67 /*********************************************************************
69 *********************************************************************/
73 #pragma mark Internal constants & data structs
74 #endif /* PRAGMA_MARK */
75 /*********************************************************************
76 * Internal constants & data structs
77 *********************************************************************/
78 OSKextLogSpec kOSMetaClassLogSpec
=
79 kOSKextLogErrorLevel
|
81 kOSKextLogKextBookkeepingFlag
;
84 kCompletedBootstrap
= 0,
86 kMakingDictionaries
= 2
87 } sBootstrapState
= kNoDictionaries
;
89 static const int kClassCapacityIncrement
= 40;
90 static const int kKModCapacityIncrement
= 10;
91 static OSDictionary
* sAllClassesDict
;
92 static unsigned int sDeepestClass
;
93 IOLock
* sAllClassesLock
= NULL
;
94 IOLock
* sInstancesLock
= NULL
;
97 * While loading a kext and running all its constructors to register
98 * all OSMetaClass classes, the classes are queued up here. Only one
99 * kext can be in flight at a time, guarded by sStalledClassesLock
101 static struct StalledData
{
102 const char * kextIdentifier
;
104 unsigned int capacity
;
106 OSMetaClass
** classes
;
108 IOLock
* sStalledClassesLock
= NULL
;
110 struct ExpansionData
{
111 OSOrderedSet
* instances
;
114 IOTrackingQueue
* tracking
;
120 #pragma mark OSMetaClassBase
121 #endif /* PRAGMA_MARK */
122 /*********************************************************************
124 *********************************************************************/
126 #if APPLE_KEXT_VTABLE_PADDING
127 /*********************************************************************
128 * Reserved vtable functions.
129 *********************************************************************/
131 void OSMetaClassBase::_RESERVEDOSMetaClassBase0()
132 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0); }
133 void OSMetaClassBase::_RESERVEDOSMetaClassBase1()
134 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1); }
135 void OSMetaClassBase::_RESERVEDOSMetaClassBase2()
136 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); }
137 #endif /* SLOT_USED */
139 // As these slots are used move them up inside the #if above
140 void OSMetaClassBase::_RESERVEDOSMetaClassBase3()
141 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); }
142 void OSMetaClassBase::_RESERVEDOSMetaClassBase4()
143 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); }
144 void OSMetaClassBase::_RESERVEDOSMetaClassBase5()
145 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); }
146 void OSMetaClassBase::_RESERVEDOSMetaClassBase6()
147 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); }
150 /*********************************************************************
151 * These used to be inline in the header but gcc didn't believe us
152 * Now we MUST pull the inline out at least until the compiler is
155 * Helper inlines for runtime type preprocessor macros
156 *********************************************************************/
158 /*********************************************************************
159 *********************************************************************/
161 OSMetaClassBase::safeMetaCast(
162 const OSMetaClassBase
* me
,
163 const OSMetaClass
* toType
)
165 return (me
)? me
->metaCast(toType
) : 0;
168 /*********************************************************************
169 *********************************************************************/
171 OSMetaClassBase::checkTypeInst(
172 const OSMetaClassBase
* inst
,
173 const OSMetaClassBase
* typeinst
)
175 const OSMetaClass
* toType
= OSTypeIDInst(typeinst
);
176 return typeinst
&& inst
&& (0 != inst
->metaCast(toType
));
179 /*********************************************************************
180 *********************************************************************/
181 void OSMetaClassBase::
184 sAllClassesLock
= IOLockAlloc();
185 sStalledClassesLock
= IOLockAlloc();
186 sInstancesLock
= IOLockAlloc();
189 #if APPLE_KEXT_VTABLE_PADDING
190 /*********************************************************************
191 * If you need this slot you had better setup an IOCTL style interface.
192 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU
193 * CANT change the VTABLE size ever.
194 *********************************************************************/
196 OSMetaClassBase::_RESERVEDOSMetaClassBase7()
197 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); }
200 /*********************************************************************
201 *********************************************************************/
202 OSMetaClassBase::OSMetaClassBase()
206 /*********************************************************************
207 *********************************************************************/
208 OSMetaClassBase::~OSMetaClassBase()
212 thisVTable
= (void **) this;
213 *thisVTable
= (void *) -1UL;
216 /*********************************************************************
217 *********************************************************************/
219 OSMetaClassBase::isEqualTo(const OSMetaClassBase
* anObj
) const
221 return this == anObj
;
224 /*********************************************************************
225 *********************************************************************/
227 OSMetaClassBase::metaCast(const OSMetaClass
* toMeta
) const
229 return toMeta
->checkMetaCast(this);
232 /*********************************************************************
233 *********************************************************************/
235 OSMetaClassBase::metaCast(const OSSymbol
* toMetaSymb
) const
237 return OSMetaClass::checkMetaCastWithName(toMetaSymb
, this);
240 /*********************************************************************
241 *********************************************************************/
243 OSMetaClassBase::metaCast(const OSString
* toMetaStr
) const
245 const OSSymbol
* tempSymb
= OSSymbol::withString(toMetaStr
);
246 OSMetaClassBase
* ret
= 0;
248 ret
= metaCast(tempSymb
);
254 /*********************************************************************
255 *********************************************************************/
257 OSMetaClassBase::metaCast(const char * toMetaCStr
) const
259 const OSSymbol
* tempSymb
= OSSymbol::withCString(toMetaCStr
);
260 OSMetaClassBase
* ret
= 0;
262 ret
= metaCast(tempSymb
);
269 #pragma mark OSMetaClassMeta
270 #endif /* PRAGMA_MARK */
271 /*********************************************************************
272 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass
273 *********************************************************************/
274 class OSMetaClassMeta
: public OSMetaClass
278 OSObject
* alloc() const;
280 OSMetaClassMeta::OSMetaClassMeta()
281 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass
))
283 OSObject
* OSMetaClassMeta::alloc() const { return 0; }
285 static OSMetaClassMeta sOSMetaClassMeta
;
287 const OSMetaClass
* const OSMetaClass::metaClass
= &sOSMetaClassMeta
;
288 const OSMetaClass
* OSMetaClass::getMetaClass() const
289 { return &sOSMetaClassMeta
; }
292 #pragma mark OSMetaClass
293 #endif /* PRAGMA_MARK */
294 /*********************************************************************
296 *********************************************************************/
298 #if APPLE_KEXT_VTABLE_PADDING
299 /*********************************************************************
300 * Reserved functions.
301 *********************************************************************/
302 void OSMetaClass::_RESERVEDOSMetaClass0()
303 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0); }
304 void OSMetaClass::_RESERVEDOSMetaClass1()
305 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1); }
306 void OSMetaClass::_RESERVEDOSMetaClass2()
307 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2); }
308 void OSMetaClass::_RESERVEDOSMetaClass3()
309 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3); }
310 void OSMetaClass::_RESERVEDOSMetaClass4()
311 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4); }
312 void OSMetaClass::_RESERVEDOSMetaClass5()
313 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5); }
314 void OSMetaClass::_RESERVEDOSMetaClass6()
315 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6); }
316 void OSMetaClass::_RESERVEDOSMetaClass7()
317 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7); }
320 /*********************************************************************
321 *********************************************************************/
323 OSMetaClassLogErrorForKext(
327 const char * message
= NULL
;
330 case kOSReturnSuccess
:
332 case kOSMetaClassNoInit
: // xxx - never returned; logged at fail site
333 message
= "OSMetaClass: preModLoad() wasn't called (runtime internal error).";
335 case kOSMetaClassNoDicts
:
336 message
= "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries.";
338 case kOSMetaClassNoKModSet
:
339 message
= "OSMetaClass: Allocation failure for internal kext recording set/set missing.";
341 case kOSMetaClassNoInsKModSet
:
342 message
= "OSMetaClass: Failed to record class in kext.";
344 case kOSMetaClassDuplicateClass
:
345 message
= "OSMetaClass: Duplicate class encountered.";
347 case kOSMetaClassNoSuper
: // xxx - never returned
348 message
= "OSMetaClass: Can't associate a class with its superclass.";
350 case kOSMetaClassInstNoSuper
: // xxx - never returned
351 message
= "OSMetaClass: Instance construction error; unknown superclass.";
353 case kOSMetaClassNoKext
:
354 message
= "OSMetaClass: Kext not found for metaclass.";
356 case kOSMetaClassInternal
:
358 message
= "OSMetaClass: Runtime internal error.";
363 OSKextLog(aKext
, kOSMetaClassLogSpec
, "%s", message
);
369 OSMetaClass::logError(OSReturn error
)
371 OSMetaClassLogErrorForKext(error
, NULL
);
374 /*********************************************************************
375 * The core constructor for a MetaClass (defined with this name always
376 * but within the scope of its represented class).
378 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(),
379 * in between calls to OSMetaClass::preModLoad(), which sets up for
380 * registration, and OSMetaClass::postModLoad(), which actually
381 * records all the class/kext relationships of the new MetaClasses.
382 *********************************************************************/
383 OSMetaClass::OSMetaClass(
384 const char * inClassName
,
385 const OSMetaClass
* inSuperClass
,
386 unsigned int inClassSize
)
389 classSize
= inClassSize
;
390 superClassLink
= inSuperClass
;
392 reserved
= IONew(ExpansionData
, 1);
393 bzero(reserved
, sizeof(ExpansionData
));
395 uint32_t numSiteQs
= 0;
396 if ((this == &OSSymbol ::gMetaClass
)
397 || (this == &OSString ::gMetaClass
)
398 || (this == &OSNumber ::gMetaClass
)
399 || (this == &OSString ::gMetaClass
)
400 || (this == &OSData ::gMetaClass
)
401 || (this == &OSDictionary::gMetaClass
)
402 || (this == &OSArray ::gMetaClass
)
403 || (this == &OSSet ::gMetaClass
)) numSiteQs
= 27;
405 reserved
->tracking
= IOTrackingQueueAlloc(inClassName
, (uintptr_t) this,
406 inClassSize
, 0, kIOTrackingQueueTypeAlloc
,
410 /* Hack alert: We are just casting inClassName and storing it in
411 * an OSString * instance variable. This may be because you can't
412 * create C++ objects in static constructors, but I really don't know!
414 className
= (const OSSymbol
*)inClassName
;
416 // sStalledClassesLock taken in preModLoad
418 /* There's no way we can look up the kext here, unfortunately.
420 OSKextLog(/* kext */ NULL
, kOSMetaClassLogSpec
,
421 "OSMetaClass: preModLoad() wasn't called for class %s "
422 "(runtime internal error).",
424 } else if (!sStalled
->result
) {
425 // Grow stalled array if neccessary
426 if (sStalled
->count
>= sStalled
->capacity
) {
427 OSMetaClass
**oldStalled
= sStalled
->classes
;
428 int oldSize
= sStalled
->capacity
* sizeof(OSMetaClass
*);
429 int newSize
= oldSize
430 + kKModCapacityIncrement
* sizeof(OSMetaClass
*);
432 sStalled
->classes
= (OSMetaClass
**)kalloc_tag(newSize
, VM_KERN_MEMORY_OSKEXT
);
433 if (!sStalled
->classes
) {
434 sStalled
->classes
= oldStalled
;
435 sStalled
->result
= kOSMetaClassNoTempData
;
439 sStalled
->capacity
+= kKModCapacityIncrement
;
440 memmove(sStalled
->classes
, oldStalled
, oldSize
);
441 kfree(oldStalled
, oldSize
);
442 OSMETA_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
445 sStalled
->classes
[sStalled
->count
++] = this;
449 /*********************************************************************
450 *********************************************************************/
451 OSMetaClass::~OSMetaClass()
453 OSKext
* myKext
= reserved
? reserved
->kext
: 0; // do not release
455 /* Hack alert: 'className' is a C string during early C++ init, and
456 * is converted to a real OSSymbol only when we record the OSKext in
457 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext.
458 * We can't safely cast or check 'className'.
460 * Also, release className *after* calling into the kext,
461 * as removeClass() may access className.
463 IOLockLock(sAllClassesLock
);
464 if (sAllClassesDict
) {
466 sAllClassesDict
->removeObject(className
);
468 sAllClassesDict
->removeObject((char *)className
);
471 IOLockUnlock(sAllClassesLock
);
474 if (myKext
->removeClass(this) != kOSReturnSuccess
) {
475 // xxx - what can we do?
477 className
->release();
480 // sStalledClassesLock taken in preModLoad
484 /* First pass find class in stalled list. If we find it that means
485 * we started C++ init with constructors but now we're tearing down
486 * because of some failure.
488 for (i
= 0; i
< sStalled
->count
; i
++) {
489 if (this == sStalled
->classes
[i
]) {
494 /* Remove this metaclass from the stalled list so postModLoad() doesn't
495 * try to register it.
497 if (i
< sStalled
->count
) {
499 if (i
< sStalled
->count
) {
500 memmove(&sStalled
->classes
[i
], &sStalled
->classes
[i
+1],
501 (sStalled
->count
- i
) * sizeof(OSMetaClass
*));
506 IOTrackingQueueFree(reserved
->tracking
);
508 IODelete(reserved
, ExpansionData
, 1);
511 /*********************************************************************
513 *********************************************************************/
514 void OSMetaClass::retain() const { }
515 void OSMetaClass::release() const { }
516 void OSMetaClass::release(__unused
int when
) const { }
517 void OSMetaClass::taggedRetain(__unused
const void * tag
) const { }
518 void OSMetaClass::taggedRelease(__unused
const void * tag
) const { }
519 void OSMetaClass::taggedRelease(__unused
const void * tag
, __unused
const int when
) const { }
520 int OSMetaClass::getRetainCount() const { return 0; }
522 /*********************************************************************
523 *********************************************************************/
525 OSMetaClass::getClassName() const
527 if (!className
) return NULL
;
528 return className
->getCStringNoCopy();
530 /*********************************************************************
531 *********************************************************************/
533 OSMetaClass::getClassNameSymbol() const
537 /*********************************************************************
538 *********************************************************************/
540 OSMetaClass::getClassSize() const
545 /*********************************************************************
546 *********************************************************************/
548 OSMetaClass::preModLoad(const char * kextIdentifier
)
550 IOLockLock(sStalledClassesLock
);
552 assert (sStalled
== NULL
);
553 sStalled
= (StalledData
*)kalloc_tag(sizeof(* sStalled
), VM_KERN_MEMORY_OSKEXT
);
555 sStalled
->classes
= (OSMetaClass
**)
556 kalloc_tag(kKModCapacityIncrement
* sizeof(OSMetaClass
*), VM_KERN_MEMORY_OSKEXT
);
557 if (!sStalled
->classes
) {
558 kfree(sStalled
, sizeof(*sStalled
));
561 OSMETA_ACCUMSIZE((kKModCapacityIncrement
* sizeof(OSMetaClass
*)) +
564 sStalled
->result
= kOSReturnSuccess
;
565 sStalled
->capacity
= kKModCapacityIncrement
;
567 sStalled
->kextIdentifier
= kextIdentifier
;
568 bzero(sStalled
->classes
, kKModCapacityIncrement
* sizeof(OSMetaClass
*));
571 // keep sStalledClassesLock locked until postModLoad
576 /*********************************************************************
577 *********************************************************************/
579 OSMetaClass::checkModLoad(void * loadHandle
)
581 return sStalled
&& loadHandle
== sStalled
&&
582 sStalled
->result
== kOSReturnSuccess
;
585 /*********************************************************************
586 *********************************************************************/
588 OSMetaClass::postModLoad(void * loadHandle
)
590 OSReturn result
= kOSReturnSuccess
;
591 OSSymbol
* myKextName
= 0; // must release
592 OSKext
* myKext
= 0; // must release
594 if (!sStalled
|| loadHandle
!= sStalled
) {
595 result
= kOSMetaClassInternal
;
599 if (sStalled
->result
) {
600 result
= sStalled
->result
;
601 } else switch (sBootstrapState
) {
603 case kNoDictionaries
:
604 sBootstrapState
= kMakingDictionaries
;
605 // No break; fall through
606 [[clang::fallthrough]];
608 case kMakingDictionaries
:
609 sAllClassesDict
= OSDictionary::withCapacity(kClassCapacityIncrement
);
610 if (!sAllClassesDict
) {
611 result
= kOSMetaClassNoDicts
;
614 sAllClassesDict
->setOptions(OSCollection::kSort
, OSCollection::kSort
);
616 // No break; fall through
617 [[clang::fallthrough]];
619 case kCompletedBootstrap
:
622 myKextName
= const_cast<OSSymbol
*>(OSSymbol::withCStringNoCopy(
623 sStalled
->kextIdentifier
));
625 if (!sStalled
->count
) {
626 break; // Nothing to do so just get out
629 myKext
= OSKext::lookupKextWithIdentifier(myKextName
);
631 result
= kOSMetaClassNoKext
;
633 /* Log this error here so we can include the kext name.
635 OSKextLog(/* kext */ NULL
, kOSMetaClassLogSpec
,
636 "OSMetaClass: Can't record classes for kext %s - kext not found.",
637 sStalled
->kextIdentifier
);
641 /* First pass checking classes aren't already loaded. If any already
642 * exist, we don't register any, and so we don't technically have
643 * to do any C++ teardown.
645 * Hack alert: me->className has been a C string until now.
646 * We only release the OSSymbol if we store the kext.
648 IOLockLock(sAllClassesLock
);
649 for (i
= 0; i
< sStalled
->count
; i
++) {
650 const OSMetaClass
* me
= sStalled
->classes
[i
];
651 OSMetaClass
* orig
= OSDynamicCast(OSMetaClass
,
652 sAllClassesDict
->getObject((const char *)me
->className
));
656 /* Log this error here so we can include the class name.
657 * xxx - we should look up the other kext that defines the class
659 OSKextLog(myKext
, kOSMetaClassLogSpec
,
660 "OSMetaClass: Kext %s class %s is a duplicate;"
661 "kext %s already has a class by that name.",
662 sStalled
->kextIdentifier
, (const char *)me
->className
,
663 ((OSKext
*)orig
->reserved
->kext
)->getIdentifierCString());
664 result
= kOSMetaClassDuplicateClass
;
667 unsigned int depth
= 1;
668 while ((me
= me
->superClassLink
)) depth
++;
669 if (depth
> sDeepestClass
) sDeepestClass
= depth
;
671 IOLockUnlock(sAllClassesLock
);
673 /* Bail if we didn't go through the entire list of new classes
674 * (if we hit a duplicate).
676 if (i
!= sStalled
->count
) {
680 // Second pass symbolling strings and inserting classes in dictionary
681 IOLockLock(sAllClassesLock
);
682 for (i
= 0; i
< sStalled
->count
; i
++) {
683 OSMetaClass
* me
= sStalled
->classes
[i
];
685 /* Hack alert: me->className has been a C string until now.
686 * We only release the OSSymbol in ~OSMetaClass()
687 * if we set the reference to the kext.
690 OSSymbol::withCStringNoCopy((const char *)me
->className
);
692 // xxx - I suppose if these fail we're going to panic soon....
693 sAllClassesDict
->setObject(me
->className
, me
);
695 /* Do not retain the kext object here.
697 me
->reserved
->kext
= myKext
;
699 result
= myKext
->addClass(me
, sStalled
->count
);
700 if (result
!= kOSReturnSuccess
) {
701 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */
706 IOLockUnlock(sAllClassesLock
);
707 sBootstrapState
= kCompletedBootstrap
;
712 result
= kOSMetaClassInternal
;
717 /* Don't call logError() for success or the conditions logged above
718 * or by called function.
720 if (result
!= kOSReturnSuccess
&&
721 result
!= kOSMetaClassNoInsKModSet
&&
722 result
!= kOSMetaClassDuplicateClass
&&
723 result
!= kOSMetaClassNoKext
) {
725 OSMetaClassLogErrorForKext(result
, myKext
);
728 OSSafeReleaseNULL(myKextName
);
729 OSSafeReleaseNULL(myKext
);
732 OSMETA_ACCUMSIZE(-(sStalled
->capacity
* sizeof(OSMetaClass
*) +
734 kfree(sStalled
->classes
, sStalled
->capacity
* sizeof(OSMetaClass
*));
735 kfree(sStalled
, sizeof(*sStalled
));
739 IOLockUnlock(sStalledClassesLock
);
745 /*********************************************************************
746 *********************************************************************/
748 OSMetaClass::instanceConstructed() const
750 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink)
751 if ((0 == OSIncrementAtomic(&instanceCount
)) && superClassLink
) {
752 superClassLink
->instanceConstructed();
756 /*********************************************************************
757 *********************************************************************/
759 OSMetaClass::instanceDestructed() const
761 if ((1 == OSDecrementAtomic(&instanceCount
)) && superClassLink
) {
762 superClassLink
->instanceDestructed();
765 if (((int)instanceCount
) < 0) {
766 OSKext
* myKext
= reserved
->kext
;
768 OSKextLog(myKext
, kOSMetaClassLogSpec
,
769 // xxx - this phrasing is rather cryptic
770 "OSMetaClass: Class %s - bad retain (%d)",
771 getClassName(), instanceCount
);
775 /*********************************************************************
776 *********************************************************************/
778 OSMetaClass::modHasInstance(const char * kextIdentifier
)
781 OSKext
* theKext
= NULL
; // must release
783 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
788 result
= theKext
->hasOSMetaClassInstances();
791 OSSafeReleaseNULL(theKext
);
795 /*********************************************************************
796 *********************************************************************/
798 OSMetaClass::reportModInstances(const char * kextIdentifier
)
800 OSKext::reportOSMetaClassInstances(kextIdentifier
,
801 kOSKextLogExplicitLevel
);
804 /*********************************************************************
805 *********************************************************************/
808 OSMetaClass::addInstance(const OSObject
* instance
, bool super
) const
810 if (!super
) IOLockLock(sInstancesLock
);
812 if (!reserved
->instances
) {
813 reserved
->instances
= OSOrderedSet::withCapacity(16);
814 if (superClassLink
) {
815 superClassLink
->addInstance(reserved
->instances
, true);
818 reserved
->instances
->setLastObject(instance
);
820 if (!super
) IOLockUnlock(sInstancesLock
);
824 OSMetaClass::removeInstance(const OSObject
* instance
, bool super
) const
826 if (!super
) IOLockLock(sInstancesLock
);
828 if (reserved
->instances
) {
829 reserved
->instances
->removeObject(instance
);
830 if (0 == reserved
->instances
->getCount()) {
831 if (superClassLink
) {
832 superClassLink
->removeInstance(reserved
->instances
, true);
834 IOLockLock(sAllClassesLock
);
835 reserved
->instances
->release();
836 reserved
->instances
= 0;
837 IOLockUnlock(sAllClassesLock
);
841 if (!super
) IOLockUnlock(sInstancesLock
);
845 OSMetaClass::applyToInstances(OSOrderedSet
* set
,
846 OSMetaClassInstanceApplierFunction applier
,
849 enum { kLocalDepth
= 24 };
850 unsigned int _nextIndex
[kLocalDepth
];
851 OSOrderedSet
* _sets
[kLocalDepth
];
852 unsigned int * nextIndex
= &_nextIndex
[0];
853 OSOrderedSet
** sets
= &_sets
[0];
855 OSOrderedSet
* childSet
;
856 unsigned int maxDepth
;
861 maxDepth
= sDeepestClass
;
862 if (maxDepth
> kLocalDepth
)
864 nextIndex
= IONew(typeof(nextIndex
[0]), maxDepth
);
865 sets
= IONew(typeof(sets
[0]), maxDepth
);
872 while (!done
&& (obj
= set
->getObject(idx
++)))
874 if ((childSet
= OSDynamicCast(OSOrderedSet
, obj
)))
876 if (level
>= maxDepth
) panic(">maxDepth");
878 nextIndex
[level
] = idx
;
884 done
= (*applier
)(obj
, context
);
892 idx
= nextIndex
[level
];
897 if (maxDepth
> kLocalDepth
)
899 IODelete(nextIndex
, typeof(nextIndex
[0]), maxDepth
);
900 IODelete(sets
, typeof(sets
[0]), maxDepth
);
905 OSMetaClass::applyToInstances(OSMetaClassInstanceApplierFunction applier
,
906 void * context
) const
908 IOLockLock(sInstancesLock
);
909 if (reserved
->instances
) applyToInstances(reserved
->instances
, applier
, context
);
910 IOLockUnlock(sInstancesLock
);
914 OSMetaClass::applyToInstancesOfClassName(
915 const OSSymbol
* name
,
916 OSMetaClassInstanceApplierFunction applier
,
920 OSOrderedSet
* set
= 0;
922 IOLockLock(sAllClassesLock
);
924 && (meta
= (OSMetaClass
*) sAllClassesDict
->getObject(name
))
925 && (set
= meta
->reserved
->instances
))
929 IOLockUnlock(sAllClassesLock
);
933 IOLockLock(sInstancesLock
);
934 applyToInstances(set
, applier
, context
);
935 IOLockUnlock(sInstancesLock
);
939 /*********************************************************************
940 *********************************************************************/
942 OSMetaClass::considerUnloads()
944 OSKext::considerUnloads();
947 /*********************************************************************
948 *********************************************************************/
950 OSMetaClass::getMetaClassWithName(const OSSymbol
* name
)
952 OSMetaClass
* retMeta
= 0;
958 IOLockLock(sAllClassesLock
);
959 if (sAllClassesDict
) {
960 retMeta
= (OSMetaClass
*) sAllClassesDict
->getObject(name
);
962 IOLockUnlock(sAllClassesLock
);
967 /*********************************************************************
968 *********************************************************************/
970 OSMetaClass::allocClassWithName(const OSSymbol
* name
)
972 OSObject
* result
= 0;
974 const OSMetaClass
* const meta
= getMetaClassWithName(name
);
977 result
= meta
->alloc();
983 /*********************************************************************
984 *********************************************************************/
986 OSMetaClass::allocClassWithName(const OSString
* name
)
988 const OSSymbol
* tmpKey
= OSSymbol::withString(name
);
989 OSObject
* result
= allocClassWithName(tmpKey
);
994 /*********************************************************************
995 *********************************************************************/
997 OSMetaClass::allocClassWithName(const char * name
)
999 const OSSymbol
* tmpKey
= OSSymbol::withCStringNoCopy(name
);
1000 OSObject
* result
= allocClassWithName(tmpKey
);
1006 /*********************************************************************
1007 *********************************************************************/
1009 OSMetaClass::checkMetaCastWithName(
1010 const OSSymbol
* name
,
1011 const OSMetaClassBase
* in
)
1013 OSMetaClassBase
* result
= 0;
1015 const OSMetaClass
* const meta
= getMetaClassWithName(name
);
1018 result
= meta
->checkMetaCast(in
);
1024 /*********************************************************************
1025 *********************************************************************/
1026 OSMetaClassBase
* OSMetaClass::
1027 checkMetaCastWithName(
1028 const OSString
* name
,
1029 const OSMetaClassBase
* in
)
1031 const OSSymbol
* tmpKey
= OSSymbol::withString(name
);
1032 OSMetaClassBase
* result
= checkMetaCastWithName(tmpKey
, in
);
1038 /*********************************************************************
1039 *********************************************************************/
1041 OSMetaClass::checkMetaCastWithName(
1043 const OSMetaClassBase
* in
)
1045 const OSSymbol
* tmpKey
= OSSymbol::withCStringNoCopy(name
);
1046 OSMetaClassBase
* result
= checkMetaCastWithName(tmpKey
, in
);
1052 /*********************************************************************
1053 * OSMetaClass::checkMetaCast()
1054 * Check to see if the 'check' object has this object in its metaclass chain.
1055 * Returns check if it is indeed a kind of the current meta class, 0 otherwise.
1057 * Generally this method is not invoked directly but is used to implement
1058 * the OSMetaClassBase::metaCast member function.
1060 * See also OSMetaClassBase::metaCast
1061 *********************************************************************/
1062 OSMetaClassBase
* OSMetaClass::checkMetaCast(
1063 const OSMetaClassBase
* check
) const
1065 const OSMetaClass
* const toMeta
= this;
1066 const OSMetaClass
* fromMeta
;
1068 for (fromMeta
= check
->getMetaClass(); ; fromMeta
= fromMeta
->superClassLink
) {
1069 if (toMeta
== fromMeta
) {
1070 return const_cast<OSMetaClassBase
*>(check
); // Discard const
1072 if (!fromMeta
->superClassLink
) {
1080 /*********************************************************************
1081 *********************************************************************/
1083 OSMetaClass::reservedCalled(int ind
) const
1085 const char * cname
= className
->getCStringNoCopy();
1086 panic("%s::_RESERVED%s%d called.", cname
, cname
, ind
);
1089 /*********************************************************************
1090 *********************************************************************/
1093 OSMetaClass::getSuperClass() const
1095 return superClassLink
;
1098 /*********************************************************************
1099 * xxx - I want to rename this :-/
1100 *********************************************************************/
1102 OSMetaClass::getKmodName() const
1104 OSKext
* myKext
= reserved
? reserved
->kext
: 0;
1106 return myKext
->getIdentifier();
1108 return OSSymbol::withCStringNoCopy("unknown");
1111 /*********************************************************************
1112 *********************************************************************/
1114 OSMetaClass::getInstanceCount() const
1116 return instanceCount
;
1119 /*********************************************************************
1120 *********************************************************************/
1123 OSMetaClass::printInstanceCounts()
1125 OSCollectionIterator
* classes
;
1126 OSSymbol
* className
;
1129 IOLockLock(sAllClassesLock
);
1130 classes
= OSCollectionIterator::withCollection(sAllClassesDict
);
1133 while( (className
= (OSSymbol
*)classes
->getNextObject())) {
1134 meta
= (OSMetaClass
*)sAllClassesDict
->getObject(className
);
1137 printf("%24s count: %03d x 0x%03x = 0x%06x\n",
1138 className
->getCStringNoCopy(),
1139 meta
->getInstanceCount(),
1140 meta
->getClassSize(),
1141 meta
->getInstanceCount() * meta
->getClassSize() );
1145 IOLockUnlock(sAllClassesLock
);
1149 /*********************************************************************
1150 *********************************************************************/
1152 OSMetaClass::getClassDictionary()
1154 panic("OSMetaClass::getClassDictionary() is obsoleted.\n");
1158 /*********************************************************************
1159 *********************************************************************/
1161 OSMetaClass::serialize(__unused OSSerialize
* s
) const
1163 panic("OSMetaClass::serialize(): Obsoleted\n");
1167 /*********************************************************************
1168 *********************************************************************/
1171 OSMetaClass::serializeClassDictionary(OSDictionary
* serializeDictionary
)
1173 OSDictionary
* classDict
= NULL
;
1175 IOLockLock(sAllClassesLock
);
1177 classDict
= OSDictionary::withCapacity(sAllClassesDict
->getCount());
1183 OSCollectionIterator
* classes
;
1184 const OSSymbol
* className
;
1186 classes
= OSCollectionIterator::withCollection(sAllClassesDict
);
1191 while ((className
= (const OSSymbol
*)classes
->getNextObject())) {
1192 const OSMetaClass
* meta
;
1195 meta
= (OSMetaClass
*)sAllClassesDict
->getObject(className
);
1196 count
= OSNumber::withNumber(meta
->getInstanceCount(), 32);
1198 classDict
->setObject(className
, count
);
1204 serializeDictionary
->setObject("Classes", classDict
);
1208 OSSafeReleaseNULL(classDict
);
1210 IOLockUnlock(sAllClassesLock
);
1216 /*********************************************************************
1217 *********************************************************************/
1221 void *OSMetaClass::trackedNew(size_t size
)
1225 mem
= (typeof(mem
)) kalloc_tag_bt(size
+ sizeof(IOTracking
), VM_KERN_MEMORY_LIBKERN
);
1227 if (!mem
) return (mem
);
1229 memset(mem
, 0, size
+ sizeof(IOTracking
));
1232 OSIVAR_ACCUMSIZE(size
);
1237 void OSMetaClass::trackedDelete(void * instance
, size_t size
)
1239 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1241 kfree(mem
, size
+ sizeof(IOTracking
));
1242 OSIVAR_ACCUMSIZE(-size
);
1245 void OSMetaClass::trackedInstance(OSObject
* instance
) const
1247 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1249 return (IOTrackingAdd(reserved
->tracking
, mem
, classSize
, false));
1252 void OSMetaClass::trackedFree(OSObject
* instance
) const
1254 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1256 return (IOTrackingRemove(reserved
->tracking
, mem
, classSize
));
1259 void OSMetaClass::trackedAccumSize(OSObject
* instance
, size_t size
) const
1261 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1263 return (IOTrackingAccumSize(reserved
->tracking
, mem
, size
));
1266 IOTrackingQueue
* OSMetaClass::getTracking() const
1268 return (reserved
->tracking
);
1271 #endif /* IOTRACKING */