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
;
115 IOTrackingQueue
* tracking
;
121 #pragma mark OSMetaClassBase
122 #endif /* PRAGMA_MARK */
123 /*********************************************************************
125 *********************************************************************/
127 #if APPLE_KEXT_VTABLE_PADDING
128 /*********************************************************************
129 * Reserved vtable functions.
130 *********************************************************************/
132 void OSMetaClassBase::_RESERVEDOSMetaClassBase0()
133 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0); }
134 void OSMetaClassBase::_RESERVEDOSMetaClassBase1()
135 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1); }
136 void OSMetaClassBase::_RESERVEDOSMetaClassBase2()
137 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); }
138 #endif /* SLOT_USED */
140 // As these slots are used move them up inside the #if above
141 void OSMetaClassBase::_RESERVEDOSMetaClassBase3()
142 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); }
143 void OSMetaClassBase::_RESERVEDOSMetaClassBase4()
144 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); }
145 void OSMetaClassBase::_RESERVEDOSMetaClassBase5()
146 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); }
147 void OSMetaClassBase::_RESERVEDOSMetaClassBase6()
148 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); }
152 /*********************************************************************
153 *********************************************************************/
155 #if defined(__arm__) || defined(__arm64__)
160 IHI0059A "C++ Application Binary Interface Standard for the ARM 64 - bit Architecture":
162 3.2.1 Representation of pointer to member function The generic C++ ABI [GC++ABI]
163 specifies that a pointer to member function is a pair of words <ptr, adj>. The
164 least significant bit of ptr discriminates between (0) the address of a non-
165 virtual member function and (1) the offset in the class's virtual table of the
166 address of a virtual function. This encoding cannot work for the AArch64
167 instruction set where the architecture reserves all bits of code addresses. This
168 ABI specifies that adj contains twice the this adjustment, plus 1 if the member
169 function is virtual. The least significant bit of adj then makes exactly the
170 same discrimination as the least significant bit of ptr does for Itanium. A
171 pointer to member function is NULL when ptr = 0 and the least significant bit of
175 OSMetaClassBase::_ptf_t
176 OSMetaClassBase::_ptmf2ptf(const OSMetaClassBase
*self
, void (OSMetaClassBase::*func
)(void))
178 typedef long int ptrdiff_t;
184 void (OSMetaClassBase::*fIn
)(void);
192 if (map
.pTMF
.delta
& 1) {
195 const OSMetaClassBase
*fObj
;
200 // Virtual member function so dereference table
201 pfn
= *(_ptf_t
*)(((uintptr_t)*u
.vtablep
) + (uintptr_t)pfn
);
205 // Not virtual, i.e. plain member func
210 #endif /* defined(__arm__) || defined(__arm64__) */
211 /*********************************************************************
212 * These used to be inline in the header but gcc didn't believe us
213 * Now we MUST pull the inline out at least until the compiler is
216 * Helper inlines for runtime type preprocessor macros
217 *********************************************************************/
219 /*********************************************************************
220 *********************************************************************/
222 OSMetaClassBase::safeMetaCast(
223 const OSMetaClassBase
* me
,
224 const OSMetaClass
* toType
)
226 return (me
)? me
->metaCast(toType
) : 0;
229 /*********************************************************************
230 *********************************************************************/
232 OSMetaClassBase::checkTypeInst(
233 const OSMetaClassBase
* inst
,
234 const OSMetaClassBase
* typeinst
)
236 const OSMetaClass
* toType
= OSTypeIDInst(typeinst
);
237 return typeinst
&& inst
&& (0 != inst
->metaCast(toType
));
240 /*********************************************************************
241 *********************************************************************/
242 void OSMetaClassBase::
245 sAllClassesLock
= IOLockAlloc();
246 sStalledClassesLock
= IOLockAlloc();
247 sInstancesLock
= IOLockAlloc();
250 #if APPLE_KEXT_VTABLE_PADDING
251 /*********************************************************************
252 * If you need this slot you had better setup an IOCTL style interface.
253 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU
254 * CANT change the VTABLE size ever.
255 *********************************************************************/
257 OSMetaClassBase::_RESERVEDOSMetaClassBase7()
258 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); }
261 /*********************************************************************
262 *********************************************************************/
263 OSMetaClassBase::OSMetaClassBase()
267 /*********************************************************************
268 *********************************************************************/
269 OSMetaClassBase::~OSMetaClassBase()
273 thisVTable
= (void **) this;
274 *thisVTable
= (void *) -1UL;
277 /*********************************************************************
278 *********************************************************************/
280 OSMetaClassBase::isEqualTo(const OSMetaClassBase
* anObj
) const
282 return this == anObj
;
285 /*********************************************************************
286 *********************************************************************/
288 OSMetaClassBase::metaCast(const OSMetaClass
* toMeta
) const
290 return toMeta
->checkMetaCast(this);
293 /*********************************************************************
294 *********************************************************************/
296 OSMetaClassBase::metaCast(const OSSymbol
* toMetaSymb
) const
298 return OSMetaClass::checkMetaCastWithName(toMetaSymb
, this);
301 /*********************************************************************
302 *********************************************************************/
304 OSMetaClassBase::metaCast(const OSString
* toMetaStr
) const
306 const OSSymbol
* tempSymb
= OSSymbol::withString(toMetaStr
);
307 OSMetaClassBase
* ret
= 0;
309 ret
= metaCast(tempSymb
);
315 /*********************************************************************
316 *********************************************************************/
318 OSMetaClassBase::metaCast(const char * toMetaCStr
) const
320 const OSSymbol
* tempSymb
= OSSymbol::withCString(toMetaCStr
);
321 OSMetaClassBase
* ret
= 0;
323 ret
= metaCast(tempSymb
);
330 #pragma mark OSMetaClassMeta
331 #endif /* PRAGMA_MARK */
332 /*********************************************************************
333 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass
334 *********************************************************************/
335 class OSMetaClassMeta
: public OSMetaClass
339 OSObject
* alloc() const;
341 OSMetaClassMeta::OSMetaClassMeta()
342 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass
))
344 OSObject
* OSMetaClassMeta::alloc() const { return 0; }
346 static OSMetaClassMeta sOSMetaClassMeta
;
348 const OSMetaClass
* const OSMetaClass::metaClass
= &sOSMetaClassMeta
;
349 const OSMetaClass
* OSMetaClass::getMetaClass() const
350 { return &sOSMetaClassMeta
; }
353 #pragma mark OSMetaClass
354 #endif /* PRAGMA_MARK */
355 /*********************************************************************
357 *********************************************************************/
359 #if APPLE_KEXT_VTABLE_PADDING
360 /*********************************************************************
361 * Reserved functions.
362 *********************************************************************/
363 void OSMetaClass::_RESERVEDOSMetaClass0()
364 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0); }
365 void OSMetaClass::_RESERVEDOSMetaClass1()
366 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1); }
367 void OSMetaClass::_RESERVEDOSMetaClass2()
368 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2); }
369 void OSMetaClass::_RESERVEDOSMetaClass3()
370 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3); }
371 void OSMetaClass::_RESERVEDOSMetaClass4()
372 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4); }
373 void OSMetaClass::_RESERVEDOSMetaClass5()
374 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5); }
375 void OSMetaClass::_RESERVEDOSMetaClass6()
376 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6); }
377 void OSMetaClass::_RESERVEDOSMetaClass7()
378 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7); }
381 /*********************************************************************
382 *********************************************************************/
384 OSMetaClassLogErrorForKext(
388 const char * message
= NULL
;
391 case kOSReturnSuccess
:
393 case kOSMetaClassNoInit
: // xxx - never returned; logged at fail site
394 message
= "OSMetaClass: preModLoad() wasn't called (runtime internal error).";
396 case kOSMetaClassNoDicts
:
397 message
= "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries.";
399 case kOSMetaClassNoKModSet
:
400 message
= "OSMetaClass: Allocation failure for internal kext recording set/set missing.";
402 case kOSMetaClassNoInsKModSet
:
403 message
= "OSMetaClass: Failed to record class in kext.";
405 case kOSMetaClassDuplicateClass
:
406 message
= "OSMetaClass: Duplicate class encountered.";
408 case kOSMetaClassNoSuper
: // xxx - never returned
409 message
= "OSMetaClass: Can't associate a class with its superclass.";
411 case kOSMetaClassInstNoSuper
: // xxx - never returned
412 message
= "OSMetaClass: Instance construction error; unknown superclass.";
414 case kOSMetaClassNoKext
:
415 message
= "OSMetaClass: Kext not found for metaclass.";
417 case kOSMetaClassInternal
:
419 message
= "OSMetaClass: Runtime internal error.";
424 OSKextLog(aKext
, kOSMetaClassLogSpec
, "%s", message
);
430 OSMetaClass::logError(OSReturn error
)
432 OSMetaClassLogErrorForKext(error
, NULL
);
435 /*********************************************************************
436 * The core constructor for a MetaClass (defined with this name always
437 * but within the scope of its represented class).
439 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(),
440 * in between calls to OSMetaClass::preModLoad(), which sets up for
441 * registration, and OSMetaClass::postModLoad(), which actually
442 * records all the class/kext relationships of the new MetaClasses.
443 *********************************************************************/
444 OSMetaClass::OSMetaClass(
445 const char * inClassName
,
446 const OSMetaClass
* inSuperClass
,
447 unsigned int inClassSize
)
450 classSize
= inClassSize
;
451 superClassLink
= inSuperClass
;
453 reserved
= IONew(ExpansionData
, 1);
454 bzero(reserved
, sizeof(ExpansionData
));
456 uint32_t numSiteQs
= 0;
457 if ((this == &OSSymbol ::gMetaClass
)
458 || (this == &OSString ::gMetaClass
)
459 || (this == &OSNumber ::gMetaClass
)
460 || (this == &OSString ::gMetaClass
)
461 || (this == &OSData ::gMetaClass
)
462 || (this == &OSDictionary::gMetaClass
)
463 || (this == &OSArray ::gMetaClass
)
464 || (this == &OSSet ::gMetaClass
)) numSiteQs
= 27;
466 reserved
->tracking
= IOTrackingQueueAlloc(inClassName
, (uintptr_t) this,
467 inClassSize
, 0, kIOTrackingQueueTypeAlloc
,
471 /* Hack alert: We are just casting inClassName and storing it in
472 * an OSString * instance variable. This may be because you can't
473 * create C++ objects in static constructors, but I really don't know!
475 className
= (const OSSymbol
*)inClassName
;
477 // sStalledClassesLock taken in preModLoad
479 /* There's no way we can look up the kext here, unfortunately.
481 OSKextLog(/* kext */ NULL
, kOSMetaClassLogSpec
,
482 "OSMetaClass: preModLoad() wasn't called for class %s "
483 "(runtime internal error).",
485 } else if (!sStalled
->result
) {
486 // Grow stalled array if neccessary
487 if (sStalled
->count
>= sStalled
->capacity
) {
488 OSMetaClass
**oldStalled
= sStalled
->classes
;
489 int oldSize
= sStalled
->capacity
* sizeof(OSMetaClass
*);
490 int newSize
= oldSize
491 + kKModCapacityIncrement
* sizeof(OSMetaClass
*);
493 sStalled
->classes
= (OSMetaClass
**)kalloc_tag(newSize
, VM_KERN_MEMORY_OSKEXT
);
494 if (!sStalled
->classes
) {
495 sStalled
->classes
= oldStalled
;
496 sStalled
->result
= kOSMetaClassNoTempData
;
500 sStalled
->capacity
+= kKModCapacityIncrement
;
501 memmove(sStalled
->classes
, oldStalled
, oldSize
);
502 kfree(oldStalled
, oldSize
);
503 OSMETA_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
506 sStalled
->classes
[sStalled
->count
++] = this;
510 /*********************************************************************
511 *********************************************************************/
512 OSMetaClass::~OSMetaClass()
514 OSKext
* myKext
= reserved
? reserved
->kext
: 0; // do not release
516 /* Hack alert: 'className' is a C string during early C++ init, and
517 * is converted to a real OSSymbol only when we record the OSKext in
518 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext.
519 * We can't safely cast or check 'className'.
521 * Also, release className *after* calling into the kext,
522 * as removeClass() may access className.
524 IOLockLock(sAllClassesLock
);
525 if (sAllClassesDict
) {
527 sAllClassesDict
->removeObject(className
);
529 sAllClassesDict
->removeObject((const char *)className
);
532 IOLockUnlock(sAllClassesLock
);
535 if (myKext
->removeClass(this) != kOSReturnSuccess
) {
536 // xxx - what can we do?
538 className
->release();
541 // sStalledClassesLock taken in preModLoad
545 /* First pass find class in stalled list. If we find it that means
546 * we started C++ init with constructors but now we're tearing down
547 * because of some failure.
549 for (i
= 0; i
< sStalled
->count
; i
++) {
550 if (this == sStalled
->classes
[i
]) {
555 /* Remove this metaclass from the stalled list so postModLoad() doesn't
556 * try to register it.
558 if (i
< sStalled
->count
) {
560 if (i
< sStalled
->count
) {
561 memmove(&sStalled
->classes
[i
], &sStalled
->classes
[i
+1],
562 (sStalled
->count
- i
) * sizeof(OSMetaClass
*));
567 IOTrackingQueueFree(reserved
->tracking
);
569 IODelete(reserved
, ExpansionData
, 1);
572 /*********************************************************************
574 *********************************************************************/
575 void OSMetaClass::retain() const { }
576 void OSMetaClass::release() const { }
577 void OSMetaClass::release(__unused
int when
) const { }
578 void OSMetaClass::taggedRetain(__unused
const void * tag
) const { }
579 void OSMetaClass::taggedRelease(__unused
const void * tag
) const { }
580 void OSMetaClass::taggedRelease(__unused
const void * tag
, __unused
const int when
) const { }
581 int OSMetaClass::getRetainCount() const { return 0; }
583 /*********************************************************************
584 *********************************************************************/
586 OSMetaClass::getClassName() const
588 if (!className
) return NULL
;
589 return className
->getCStringNoCopy();
591 /*********************************************************************
592 *********************************************************************/
594 OSMetaClass::getClassNameSymbol() const
598 /*********************************************************************
599 *********************************************************************/
601 OSMetaClass::getClassSize() const
606 /*********************************************************************
607 *********************************************************************/
609 OSMetaClass::preModLoad(const char * kextIdentifier
)
611 IOLockLock(sStalledClassesLock
);
613 assert (sStalled
== NULL
);
614 sStalled
= (StalledData
*)kalloc_tag(sizeof(* sStalled
), VM_KERN_MEMORY_OSKEXT
);
616 sStalled
->classes
= (OSMetaClass
**)
617 kalloc_tag(kKModCapacityIncrement
* sizeof(OSMetaClass
*), VM_KERN_MEMORY_OSKEXT
);
618 if (!sStalled
->classes
) {
619 kfree(sStalled
, sizeof(*sStalled
));
622 OSMETA_ACCUMSIZE((kKModCapacityIncrement
* sizeof(OSMetaClass
*)) +
625 sStalled
->result
= kOSReturnSuccess
;
626 sStalled
->capacity
= kKModCapacityIncrement
;
628 sStalled
->kextIdentifier
= kextIdentifier
;
629 bzero(sStalled
->classes
, kKModCapacityIncrement
* sizeof(OSMetaClass
*));
632 // keep sStalledClassesLock locked until postModLoad
637 /*********************************************************************
638 *********************************************************************/
640 OSMetaClass::checkModLoad(void * loadHandle
)
642 return sStalled
&& loadHandle
== sStalled
&&
643 sStalled
->result
== kOSReturnSuccess
;
646 /*********************************************************************
647 *********************************************************************/
649 OSMetaClass::postModLoad(void * loadHandle
)
651 OSReturn result
= kOSReturnSuccess
;
652 OSSymbol
* myKextName
= 0; // must release
653 OSKext
* myKext
= 0; // must release
655 if (!sStalled
|| loadHandle
!= sStalled
) {
656 result
= kOSMetaClassInternal
;
660 if (sStalled
->result
) {
661 result
= sStalled
->result
;
662 } else switch (sBootstrapState
) {
664 case kNoDictionaries
:
665 sBootstrapState
= kMakingDictionaries
;
666 // No break; fall through
667 [[clang::fallthrough]];
669 case kMakingDictionaries
:
670 sAllClassesDict
= OSDictionary::withCapacity(kClassCapacityIncrement
);
671 if (!sAllClassesDict
) {
672 result
= kOSMetaClassNoDicts
;
675 sAllClassesDict
->setOptions(OSCollection::kSort
, OSCollection::kSort
);
677 // No break; fall through
678 [[clang::fallthrough]];
680 case kCompletedBootstrap
:
683 myKextName
= const_cast<OSSymbol
*>(OSSymbol::withCStringNoCopy(
684 sStalled
->kextIdentifier
));
686 if (!sStalled
->count
) {
687 break; // Nothing to do so just get out
690 myKext
= OSKext::lookupKextWithIdentifier(myKextName
);
692 result
= kOSMetaClassNoKext
;
694 /* Log this error here so we can include the kext name.
696 OSKextLog(/* kext */ NULL
, kOSMetaClassLogSpec
,
697 "OSMetaClass: Can't record classes for kext %s - kext not found.",
698 sStalled
->kextIdentifier
);
702 /* First pass checking classes aren't already loaded. If any already
703 * exist, we don't register any, and so we don't technically have
704 * to do any C++ teardown.
706 * Hack alert: me->className has been a C string until now.
707 * We only release the OSSymbol if we store the kext.
709 IOLockLock(sAllClassesLock
);
710 for (i
= 0; i
< sStalled
->count
; i
++) {
711 const OSMetaClass
* me
= sStalled
->classes
[i
];
712 OSMetaClass
* orig
= OSDynamicCast(OSMetaClass
,
713 sAllClassesDict
->getObject((const char *)me
->className
));
717 /* Log this error here so we can include the class name.
718 * xxx - we should look up the other kext that defines the class
723 OSKextLog(myKext
, kOSMetaClassLogSpec
,
724 #endif /* CONFIG_EMBEDDED */
725 "OSMetaClass: Kext %s class %s is a duplicate;"
726 "kext %s already has a class by that name.",
727 sStalled
->kextIdentifier
, (const char *)me
->className
,
728 ((OSKext
*)orig
->reserved
->kext
)->getIdentifierCString());
729 result
= kOSMetaClassDuplicateClass
;
732 unsigned int depth
= 1;
733 while ((me
= me
->superClassLink
)) depth
++;
734 if (depth
> sDeepestClass
) sDeepestClass
= depth
;
736 IOLockUnlock(sAllClassesLock
);
738 /* Bail if we didn't go through the entire list of new classes
739 * (if we hit a duplicate).
741 if (i
!= sStalled
->count
) {
745 // Second pass symbolling strings and inserting classes in dictionary
746 IOLockLock(sAllClassesLock
);
747 for (i
= 0; i
< sStalled
->count
; i
++) {
748 OSMetaClass
* me
= sStalled
->classes
[i
];
750 /* Hack alert: me->className has been a C string until now.
751 * We only release the OSSymbol in ~OSMetaClass()
752 * if we set the reference to the kext.
755 OSSymbol::withCStringNoCopy((const char *)me
->className
);
757 // xxx - I suppose if these fail we're going to panic soon....
758 sAllClassesDict
->setObject(me
->className
, me
);
760 /* Do not retain the kext object here.
762 me
->reserved
->kext
= myKext
;
764 result
= myKext
->addClass(me
, sStalled
->count
);
765 if (result
!= kOSReturnSuccess
) {
766 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */
771 IOLockUnlock(sAllClassesLock
);
772 sBootstrapState
= kCompletedBootstrap
;
777 result
= kOSMetaClassInternal
;
782 /* Don't call logError() for success or the conditions logged above
783 * or by called function.
785 if (result
!= kOSReturnSuccess
&&
786 result
!= kOSMetaClassNoInsKModSet
&&
787 result
!= kOSMetaClassDuplicateClass
&&
788 result
!= kOSMetaClassNoKext
) {
790 OSMetaClassLogErrorForKext(result
, myKext
);
793 OSSafeReleaseNULL(myKextName
);
794 OSSafeReleaseNULL(myKext
);
797 OSMETA_ACCUMSIZE(-(sStalled
->capacity
* sizeof(OSMetaClass
*) +
799 kfree(sStalled
->classes
, sStalled
->capacity
* sizeof(OSMetaClass
*));
800 kfree(sStalled
, sizeof(*sStalled
));
804 IOLockUnlock(sStalledClassesLock
);
810 /*********************************************************************
811 *********************************************************************/
813 OSMetaClass::instanceConstructed() const
815 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink)
816 if ((0 == OSIncrementAtomic(&instanceCount
)) && superClassLink
) {
817 superClassLink
->instanceConstructed();
821 /*********************************************************************
822 *********************************************************************/
824 OSMetaClass::instanceDestructed() const
826 if ((1 == OSDecrementAtomic(&instanceCount
)) && superClassLink
) {
827 superClassLink
->instanceDestructed();
830 if (((int)instanceCount
) < 0) {
831 OSKext
* myKext
= reserved
->kext
;
833 OSKextLog(myKext
, kOSMetaClassLogSpec
,
834 // xxx - this phrasing is rather cryptic
835 "OSMetaClass: Class %s - bad retain (%d)",
836 getClassName(), instanceCount
);
840 /*********************************************************************
841 *********************************************************************/
843 OSMetaClass::modHasInstance(const char * kextIdentifier
)
846 OSKext
* theKext
= NULL
; // must release
848 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
853 result
= theKext
->hasOSMetaClassInstances();
856 OSSafeReleaseNULL(theKext
);
860 /*********************************************************************
861 *********************************************************************/
863 OSMetaClass::reportModInstances(const char * kextIdentifier
)
865 OSKext::reportOSMetaClassInstances(kextIdentifier
,
866 kOSKextLogExplicitLevel
);
869 /*********************************************************************
870 *********************************************************************/
873 OSMetaClass::addInstance(const OSObject
* instance
, bool super
) const
875 if (!super
) IOLockLock(sInstancesLock
);
877 if (!reserved
->instances
) {
878 reserved
->instances
= OSOrderedSet::withCapacity(16);
879 if (superClassLink
) {
880 superClassLink
->addInstance(reserved
->instances
, true);
883 reserved
->instances
->setLastObject(instance
);
885 if (!super
) IOLockUnlock(sInstancesLock
);
889 OSMetaClass::removeInstance(const OSObject
* instance
, bool super
) const
891 if (!super
) IOLockLock(sInstancesLock
);
893 if (reserved
->instances
) {
894 reserved
->instances
->removeObject(instance
);
895 if (0 == reserved
->instances
->getCount()) {
896 if (superClassLink
) {
897 superClassLink
->removeInstance(reserved
->instances
, true);
899 IOLockLock(sAllClassesLock
);
900 reserved
->instances
->release();
901 reserved
->instances
= 0;
902 IOLockUnlock(sAllClassesLock
);
906 if (!super
) IOLockUnlock(sInstancesLock
);
910 OSMetaClass::applyToInstances(OSOrderedSet
* set
,
911 OSMetaClassInstanceApplierFunction applier
,
914 enum { kLocalDepth
= 24 };
915 unsigned int _nextIndex
[kLocalDepth
];
916 OSOrderedSet
* _sets
[kLocalDepth
];
917 unsigned int * nextIndex
= &_nextIndex
[0];
918 OSOrderedSet
** sets
= &_sets
[0];
920 OSOrderedSet
* childSet
;
921 unsigned int maxDepth
;
926 maxDepth
= sDeepestClass
;
927 if (maxDepth
> kLocalDepth
)
929 nextIndex
= IONew(typeof(nextIndex
[0]), maxDepth
);
930 sets
= IONew(typeof(sets
[0]), maxDepth
);
937 while (!done
&& (obj
= set
->getObject(idx
++)))
939 if ((childSet
= OSDynamicCast(OSOrderedSet
, obj
)))
941 if (level
>= maxDepth
) panic(">maxDepth");
943 nextIndex
[level
] = idx
;
949 done
= (*applier
)(obj
, context
);
957 idx
= nextIndex
[level
];
962 if (maxDepth
> kLocalDepth
)
964 IODelete(nextIndex
, typeof(nextIndex
[0]), maxDepth
);
965 IODelete(sets
, typeof(sets
[0]), maxDepth
);
970 OSMetaClass::applyToInstances(OSMetaClassInstanceApplierFunction applier
,
971 void * context
) const
973 IOLockLock(sInstancesLock
);
974 if (reserved
->instances
) applyToInstances(reserved
->instances
, applier
, context
);
975 IOLockUnlock(sInstancesLock
);
979 OSMetaClass::applyToInstancesOfClassName(
980 const OSSymbol
* name
,
981 OSMetaClassInstanceApplierFunction applier
,
985 OSOrderedSet
* set
= 0;
987 IOLockLock(sAllClassesLock
);
989 && (meta
= (OSMetaClass
*) sAllClassesDict
->getObject(name
))
990 && (set
= meta
->reserved
->instances
))
994 IOLockUnlock(sAllClassesLock
);
998 IOLockLock(sInstancesLock
);
999 applyToInstances(set
, applier
, context
);
1000 IOLockUnlock(sInstancesLock
);
1004 /*********************************************************************
1005 *********************************************************************/
1007 OSMetaClass::considerUnloads()
1009 OSKext::considerUnloads();
1012 /*********************************************************************
1013 *********************************************************************/
1015 OSMetaClass::removeClasses(OSCollection
* metaClasses
)
1017 OSCollectionIterator
* classIterator
;
1018 OSMetaClass
* checkClass
;
1021 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
1022 if (!classIterator
) return (false);
1024 IOLockLock(sAllClassesLock
);
1029 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())
1030 && !checkClass
->getInstanceCount()
1031 && !checkClass
->reserved
->retain
) {}
1032 if (checkClass
) break;
1033 classIterator
->reset();
1034 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject()))
1036 sAllClassesDict
->removeObject(checkClass
->className
);
1042 IOLockUnlock(sAllClassesLock
);
1043 OSSafeReleaseNULL(classIterator
);
1049 /*********************************************************************
1050 *********************************************************************/
1052 OSMetaClass::getMetaClassWithName(const OSSymbol
* name
)
1054 OSMetaClass
* retMeta
= 0;
1060 IOLockLock(sAllClassesLock
);
1061 if (sAllClassesDict
) {
1062 retMeta
= (OSMetaClass
*) sAllClassesDict
->getObject(name
);
1064 IOLockUnlock(sAllClassesLock
);
1069 /*********************************************************************
1070 *********************************************************************/
1072 OSMetaClass::copyMetaClassWithName(const OSSymbol
* name
)
1074 const OSMetaClass
* meta
;
1076 if (!name
) return (0);
1079 IOLockLock(sAllClassesLock
);
1080 if (sAllClassesDict
) {
1081 meta
= (OSMetaClass
*) sAllClassesDict
->getObject(name
);
1082 if (meta
) OSIncrementAtomic(&meta
->reserved
->retain
);
1084 IOLockUnlock(sAllClassesLock
);
1089 /*********************************************************************
1090 *********************************************************************/
1092 OSMetaClass::releaseMetaClass() const
1094 OSDecrementAtomic(&reserved
->retain
);
1097 /*********************************************************************
1098 *********************************************************************/
1100 OSMetaClass::allocClassWithName(const OSSymbol
* name
)
1102 const OSMetaClass
* meta
;
1106 meta
= copyMetaClassWithName(name
);
1109 result
= meta
->alloc();
1110 meta
->releaseMetaClass();
1116 /*********************************************************************
1117 *********************************************************************/
1119 OSMetaClass::allocClassWithName(const OSString
* name
)
1121 const OSSymbol
* tmpKey
= OSSymbol::withString(name
);
1122 OSObject
* result
= allocClassWithName(tmpKey
);
1127 /*********************************************************************
1128 *********************************************************************/
1130 OSMetaClass::allocClassWithName(const char * name
)
1132 const OSSymbol
* tmpKey
= OSSymbol::withCStringNoCopy(name
);
1133 OSObject
* result
= allocClassWithName(tmpKey
);
1139 /*********************************************************************
1140 *********************************************************************/
1142 OSMetaClass::checkMetaCastWithName(
1143 const OSSymbol
* name
,
1144 const OSMetaClassBase
* in
)
1146 OSMetaClassBase
* result
= 0;
1148 const OSMetaClass
* const meta
= getMetaClassWithName(name
);
1151 result
= meta
->checkMetaCast(in
);
1157 /*********************************************************************
1158 *********************************************************************/
1159 OSMetaClassBase
* OSMetaClass::
1160 checkMetaCastWithName(
1161 const OSString
* name
,
1162 const OSMetaClassBase
* in
)
1164 const OSSymbol
* tmpKey
= OSSymbol::withString(name
);
1165 OSMetaClassBase
* result
= checkMetaCastWithName(tmpKey
, in
);
1171 /*********************************************************************
1172 *********************************************************************/
1174 OSMetaClass::checkMetaCastWithName(
1176 const OSMetaClassBase
* in
)
1178 const OSSymbol
* tmpKey
= OSSymbol::withCStringNoCopy(name
);
1179 OSMetaClassBase
* result
= checkMetaCastWithName(tmpKey
, in
);
1185 /*********************************************************************
1186 * OSMetaClass::checkMetaCast()
1187 * Check to see if the 'check' object has this object in its metaclass chain.
1188 * Returns check if it is indeed a kind of the current meta class, 0 otherwise.
1190 * Generally this method is not invoked directly but is used to implement
1191 * the OSMetaClassBase::metaCast member function.
1193 * See also OSMetaClassBase::metaCast
1194 *********************************************************************/
1195 OSMetaClassBase
* OSMetaClass::checkMetaCast(
1196 const OSMetaClassBase
* check
) const
1198 const OSMetaClass
* const toMeta
= this;
1199 const OSMetaClass
* fromMeta
;
1201 for (fromMeta
= check
->getMetaClass(); ; fromMeta
= fromMeta
->superClassLink
) {
1202 if (toMeta
== fromMeta
) {
1203 return const_cast<OSMetaClassBase
*>(check
); // Discard const
1205 if (!fromMeta
->superClassLink
) {
1213 /*********************************************************************
1214 *********************************************************************/
1216 OSMetaClass::reservedCalled(int ind
) const
1218 const char * cname
= className
->getCStringNoCopy();
1219 panic("%s::_RESERVED%s%d called.", cname
, cname
, ind
);
1222 /*********************************************************************
1223 *********************************************************************/
1226 OSMetaClass::getSuperClass() const
1228 return superClassLink
;
1231 /*********************************************************************
1232 * xxx - I want to rename this :-/
1233 *********************************************************************/
1235 OSMetaClass::getKmodName() const
1237 OSKext
* myKext
= reserved
? reserved
->kext
: 0;
1239 return myKext
->getIdentifier();
1241 return OSSymbol::withCStringNoCopy("unknown");
1244 /*********************************************************************
1245 *********************************************************************/
1247 OSMetaClass::getInstanceCount() const
1249 return instanceCount
;
1252 /*********************************************************************
1253 *********************************************************************/
1256 OSMetaClass::printInstanceCounts()
1258 OSCollectionIterator
* classes
;
1259 OSSymbol
* className
;
1262 IOLockLock(sAllClassesLock
);
1263 classes
= OSCollectionIterator::withCollection(sAllClassesDict
);
1266 while( (className
= (OSSymbol
*)classes
->getNextObject())) {
1267 meta
= (OSMetaClass
*)sAllClassesDict
->getObject(className
);
1270 printf("%24s count: %03d x 0x%03x = 0x%06x\n",
1271 className
->getCStringNoCopy(),
1272 meta
->getInstanceCount(),
1273 meta
->getClassSize(),
1274 meta
->getInstanceCount() * meta
->getClassSize() );
1278 IOLockUnlock(sAllClassesLock
);
1282 /*********************************************************************
1283 *********************************************************************/
1285 OSMetaClass::getClassDictionary()
1287 panic("OSMetaClass::getClassDictionary() is obsoleted.\n");
1291 /*********************************************************************
1292 *********************************************************************/
1294 OSMetaClass::serialize(__unused OSSerialize
* s
) const
1296 panic("OSMetaClass::serialize(): Obsoleted\n");
1300 /*********************************************************************
1301 *********************************************************************/
1304 OSMetaClass::serializeClassDictionary(OSDictionary
* serializeDictionary
)
1306 OSDictionary
* classDict
= NULL
;
1308 IOLockLock(sAllClassesLock
);
1310 classDict
= OSDictionary::withCapacity(sAllClassesDict
->getCount());
1316 OSCollectionIterator
* classes
;
1317 const OSSymbol
* className
;
1319 classes
= OSCollectionIterator::withCollection(sAllClassesDict
);
1324 while ((className
= (const OSSymbol
*)classes
->getNextObject())) {
1325 const OSMetaClass
* meta
;
1328 meta
= (OSMetaClass
*)sAllClassesDict
->getObject(className
);
1329 count
= OSNumber::withNumber(meta
->getInstanceCount(), 32);
1331 classDict
->setObject(className
, count
);
1337 serializeDictionary
->setObject("Classes", classDict
);
1341 OSSafeReleaseNULL(classDict
);
1343 IOLockUnlock(sAllClassesLock
);
1349 /*********************************************************************
1350 *********************************************************************/
1354 void *OSMetaClass::trackedNew(size_t size
)
1358 mem
= (typeof(mem
)) kalloc_tag_bt(size
+ sizeof(IOTracking
), VM_KERN_MEMORY_LIBKERN
);
1360 if (!mem
) return (mem
);
1362 memset(mem
, 0, size
+ sizeof(IOTracking
));
1365 OSIVAR_ACCUMSIZE(size
);
1370 void OSMetaClass::trackedDelete(void * instance
, size_t size
)
1372 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1374 kfree(mem
, size
+ sizeof(IOTracking
));
1375 OSIVAR_ACCUMSIZE(-size
);
1378 void OSMetaClass::trackedInstance(OSObject
* instance
) const
1380 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1382 return (IOTrackingAdd(reserved
->tracking
, mem
, classSize
, false, VM_KERN_MEMORY_NONE
));
1385 void OSMetaClass::trackedFree(OSObject
* instance
) const
1387 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1389 return (IOTrackingRemove(reserved
->tracking
, mem
, classSize
));
1392 void OSMetaClass::trackedAccumSize(OSObject
* instance
, size_t size
) const
1394 IOTracking
* mem
= (typeof(mem
)) instance
; mem
--;
1396 return (IOTrackingAccumSize(reserved
->tracking
, mem
, size
));
1399 IOTrackingQueue
* OSMetaClass::getTracking() const
1401 return (reserved
->tracking
);
1404 #endif /* IOTRACKING */