]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSMetaClass.cpp
xnu-6153.101.6.tar.gz
[apple/xnu.git] / libkern / c++ / OSMetaClass.cpp
1 /*
2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* OSMetaClass.cpp created by gvdl on Fri 1998-11-17 */
29
30 #include <string.h>
31
32 #include <libkern/OSReturn.h>
33
34 #include <libkern/c++/OSMetaClass.h>
35 #include <libkern/c++/OSObject.h>
36 #include <libkern/c++/OSKext.h>
37
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>
45
46 #include <libkern/c++/OSLib.h>
47 #include <libkern/OSAtomic.h>
48
49 #include <IOKit/IOLib.h>
50
51 #include <IOKit/IOKitDebug.h>
52
53
54 __BEGIN_DECLS
55
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>
63 #include <stddef.h>
64
65 #if PRAGMA_MARK
66 #pragma mark Macros
67 #endif /* PRAGMA_MARK */
68 /*********************************************************************
69 * Macros
70 *********************************************************************/
71 __END_DECLS
72
73 #if PRAGMA_MARK
74 #pragma mark Internal constants & data structs
75 #endif /* PRAGMA_MARK */
76 /*********************************************************************
77 * Internal constants & data structs
78 *********************************************************************/
79 OSKextLogSpec kOSMetaClassLogSpec =
80 kOSKextLogErrorLevel |
81 kOSKextLogLoadFlag |
82 kOSKextLogKextBookkeepingFlag;
83
84 static enum {
85 kCompletedBootstrap = 0,
86 kNoDictionaries = 1,
87 kMakingDictionaries = 2
88 } sBootstrapState = kNoDictionaries;
89
90 static const int kClassCapacityIncrement = 40;
91 static const int kKModCapacityIncrement = 10;
92 static OSDictionary * sAllClassesDict;
93 static unsigned int sDeepestClass;
94 IOLock * sAllClassesLock = NULL;
95 IOLock * sInstancesLock = NULL;
96
97 /*
98 * While loading a kext and running all its constructors to register
99 * all OSMetaClass classes, the classes are queued up here. Only one
100 * kext can be in flight at a time, guarded by sStalledClassesLock
101 */
102 static struct StalledData {
103 const char * kextIdentifier;
104 OSReturn result;
105 unsigned int capacity;
106 unsigned int count;
107 OSMetaClass ** classes;
108 } * sStalled;
109 IOLock * sStalledClassesLock = NULL;
110
111 struct ExpansionData {
112 OSOrderedSet * instances;
113 OSKext * kext;
114 uint32_t retain;
115 #if IOTRACKING
116 IOTrackingQueue * tracking;
117 #endif
118 };
119
120
121 #if PRAGMA_MARK
122 #pragma mark OSMetaClassBase
123 #endif /* PRAGMA_MARK */
124 /*********************************************************************
125 * OSMetaClassBase.
126 *********************************************************************/
127
128 #if APPLE_KEXT_VTABLE_PADDING
129 /*********************************************************************
130 * Reserved vtable functions.
131 *********************************************************************/
132 #if SLOT_USED
133 void
134 OSMetaClassBase::_RESERVEDOSMetaClassBase0()
135 {
136 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0);
137 }
138 void
139 OSMetaClassBase::_RESERVEDOSMetaClassBase1()
140 {
141 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1);
142 }
143 void
144 OSMetaClassBase::_RESERVEDOSMetaClassBase2()
145 {
146 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2);
147 }
148 void
149 OSMetaClassBase::_RESERVEDOSMetaClassBase3()
150 {
151 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3);
152 }
153 #endif /* SLOT_USED */
154
155 // As these slots are used move them up inside the #if above
156 void
157 OSMetaClassBase::_RESERVEDOSMetaClassBase4()
158 {
159 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4);
160 }
161 void
162 OSMetaClassBase::_RESERVEDOSMetaClassBase5()
163 {
164 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5);
165 }
166 void
167 OSMetaClassBase::_RESERVEDOSMetaClassBase6()
168 {
169 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6);
170 }
171 #endif
172
173 /*********************************************************************
174 *********************************************************************/
175
176 #if defined(__arm__) || defined(__arm64__)
177
178 #if defined(HAS_APPLE_PAC)
179 #include <ptrauth.h>
180 #endif /* defined(HAS_APPLE_PAC) */
181
182 /*
183 * IHI0059A "C++ Application Binary Interface Standard for the ARM 64 - bit Architecture":
184 *
185 * 3.2.1 Representation of pointer to member function The generic C++ ABI [GC++ABI]
186 * specifies that a pointer to member function is a pair of words <ptr, adj>. The
187 * least significant bit of ptr discriminates between (0) the address of a non-
188 * virtual member function and (1) the offset in the class's virtual table of the
189 * address of a virtual function. This encoding cannot work for the AArch64
190 * instruction set where the architecture reserves all bits of code addresses. This
191 * ABI specifies that adj contains twice the this adjustment, plus 1 if the member
192 * function is virtual. The least significant bit of adj then makes exactly the
193 * same discrimination as the least significant bit of ptr does for Itanium. A
194 * pointer to member function is NULL when ptr = 0 and the least significant bit of
195 * adj is zero.
196 */
197
198 OSMetaClassBase::_ptf_t
199 #if defined(HAS_APPLE_PAC) && __has_feature(ptrauth_type_discriminator)
200 OSMetaClassBase::_ptmf2ptf(const OSMetaClassBase *self __attribute__((unused)),
201 void (OSMetaClassBase::*func)(void), uintptr_t typeDisc)
202 #else
203 OSMetaClassBase::_ptmf2ptf(const OSMetaClassBase *self,
204 void (OSMetaClassBase::*func)(void),
205 uintptr_t typeDisc
206 __attribute__((unused)))
207 #endif
208 {
209 struct ptmf_t {
210 _ptf_t fPFN;
211 ptrdiff_t delta;
212 };
213 union {
214 void (OSMetaClassBase::*fIn)(void);
215 struct ptmf_t pTMF;
216 } map;
217 _ptf_t pfn;
218
219 map.fIn = func;
220 pfn = map.pTMF.fPFN;
221
222 #if defined(HAS_APPLE_PAC) && __has_feature(ptrauth_type_discriminator)
223 // Authenticate 'pfn' using the member function pointer type discriminator
224 // and resign it as a C function pointer. 'pfn' can point to either a
225 // non-virtual function or a virtual member function thunk.
226 pfn = ptrauth_auth_function(pfn, ptrauth_key_function_pointer, typeDisc);
227 return pfn;
228 #else
229 if (map.pTMF.delta & 1) {
230 // virtual
231 union {
232 const OSMetaClassBase *fObj;
233 _ptf_t **vtablep;
234 } u;
235 u.fObj = self;
236
237 // Virtual member function so dereference table
238 #if defined(HAS_APPLE_PAC)
239 // The entity hash is stored in the top 32-bits of the vtable offset of a
240 // member function pointer.
241 uint32_t entity_hash = ((uintptr_t)pfn) >> 32;
242 pfn = (_ptf_t)(((uintptr_t) pfn) & 0xFFFFFFFF);
243
244 // Authenticate the vtable pointer.
245 _ptf_t *vtablep = ptrauth_auth_data(*u.vtablep,
246 ptrauth_key_cxx_vtable_pointer, 0);
247 // Calculate the address of the vtable entry.
248 _ptf_t *vtentryp = (_ptf_t *)(((uintptr_t)vtablep) + (uintptr_t)pfn);
249 // Load the pointer from the vtable entry.
250 pfn = *vtentryp;
251
252 // Finally, resign the vtable entry as a function pointer.
253 uintptr_t auth_data = ptrauth_blend_discriminator(vtentryp, entity_hash);
254 pfn = ptrauth_auth_and_resign(pfn, ptrauth_key_function_pointer,
255 auth_data, ptrauth_key_function_pointer, 0);
256 #else /* defined(HAS_APPLE_PAC) */
257 pfn = *(_ptf_t *)(((uintptr_t)*u.vtablep) + (uintptr_t)pfn);
258 #endif /* !defined(HAS_APPLE_PAC) */
259 return pfn;
260 } else {
261 // Not virtual, i.e. plain member func
262 return pfn;
263 }
264 #endif
265 }
266
267 #endif /* defined(__arm__) || defined(__arm64__) */
268 /*********************************************************************
269 * These used to be inline in the header but gcc didn't believe us
270 * Now we MUST pull the inline out at least until the compiler is
271 * repaired.
272 *
273 * Helper inlines for runtime type preprocessor macros
274 *********************************************************************/
275
276 /*********************************************************************
277 *********************************************************************/
278 OSMetaClassBase *
279 OSMetaClassBase::safeMetaCast(
280 const OSMetaClassBase * me,
281 const OSMetaClass * toType)
282 {
283 return (me)? me->metaCast(toType) : NULL;
284 }
285
286 /// A helper function to crash with a kernel panic.
287 __attribute__((cold, not_tail_called, noreturn))
288 static inline void
289 panic_crash_fail_cast(const OSMetaClassBase *me,
290 const OSMetaClass *toType)
291 {
292 panic("Unexpected cast fail: from %p to %p", me, toType);
293 __builtin_unreachable();
294 }
295
296 OSMetaClassBase *
297 OSMetaClassBase::requiredMetaCast(
298 const OSMetaClassBase * me,
299 const OSMetaClass * toType)
300 {
301 if (!me) {
302 return NULL;
303 }
304 OSMetaClassBase *tmp = safeMetaCast(me, toType);
305 if (!tmp) {
306 panic_crash_fail_cast(me, toType);
307 }
308 return tmp;
309 }
310
311 /*********************************************************************
312 *********************************************************************/
313 bool
314 OSMetaClassBase::checkTypeInst(
315 const OSMetaClassBase * inst,
316 const OSMetaClassBase * typeinst)
317 {
318 const OSMetaClass * toType = OSTypeIDInst(typeinst);
319 return typeinst && inst && (NULL != inst->metaCast(toType));
320 }
321
322 /*********************************************************************
323 *********************************************************************/
324 void
325 OSMetaClassBase::
326 initialize()
327 {
328 sAllClassesLock = IOLockAlloc();
329 sStalledClassesLock = IOLockAlloc();
330 sInstancesLock = IOLockAlloc();
331 }
332
333 #if APPLE_KEXT_VTABLE_PADDING
334 /*********************************************************************
335 * If you need this slot you had better setup an IOCTL style interface.
336 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU
337 * CANT change the VTABLE size ever.
338 *********************************************************************/
339 void
340 OSMetaClassBase::_RESERVEDOSMetaClassBase7()
341 {
342 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7);
343 }
344 #endif
345
346 /*********************************************************************
347 *********************************************************************/
348 OSMetaClassBase::OSMetaClassBase()
349 {
350 }
351
352 /*********************************************************************
353 *********************************************************************/
354 OSMetaClassBase::~OSMetaClassBase()
355 {
356 void ** thisVTable;
357
358 thisVTable = (void **) this;
359 *thisVTable = (void *) -1UL;
360 }
361
362 /*********************************************************************
363 *********************************************************************/
364 bool
365 OSMetaClassBase::isEqualTo(const OSMetaClassBase * anObj) const
366 {
367 return this == anObj;
368 }
369
370 /*********************************************************************
371 *********************************************************************/
372 OSMetaClassBase *
373 OSMetaClassBase::metaCast(const OSMetaClass * toMeta) const
374 {
375 return toMeta->checkMetaCast(this);
376 }
377
378 /*********************************************************************
379 *********************************************************************/
380 OSMetaClassBase *
381 OSMetaClassBase::metaCast(const OSSymbol * toMetaSymb) const
382 {
383 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this);
384 }
385
386 /*********************************************************************
387 *********************************************************************/
388 OSMetaClassBase *
389 OSMetaClassBase::metaCast(const OSString * toMetaStr) const
390 {
391 const OSSymbol * tempSymb = OSSymbol::withString(toMetaStr);
392 OSMetaClassBase * ret = NULL;
393 if (tempSymb) {
394 ret = metaCast(tempSymb);
395 tempSymb->release();
396 }
397 return ret;
398 }
399
400 /*********************************************************************
401 *********************************************************************/
402 OSMetaClassBase *
403 OSMetaClassBase::metaCast(const char * toMetaCStr) const
404 {
405 const OSSymbol * tempSymb = OSSymbol::withCString(toMetaCStr);
406 OSMetaClassBase * ret = NULL;
407 if (tempSymb) {
408 ret = metaCast(tempSymb);
409 tempSymb->release();
410 }
411 return ret;
412 }
413
414 #if PRAGMA_MARK
415 #pragma mark OSMetaClassMeta
416 #endif /* PRAGMA_MARK */
417 /*********************************************************************
418 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass
419 *********************************************************************/
420 class OSMetaClassMeta : public OSMetaClass
421 {
422 public:
423 OSMetaClassMeta();
424 OSObject * alloc() const;
425 };
426 OSMetaClassMeta::OSMetaClassMeta()
427 : OSMetaClass("OSMetaClass", NULL, sizeof(OSMetaClass))
428 {
429 }
430 OSObject *
431 OSMetaClassMeta::alloc() const
432 {
433 return NULL;
434 }
435
436 static OSMetaClassMeta sOSMetaClassMeta;
437
438 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta;
439 const OSMetaClass *
440 OSMetaClass::getMetaClass() const
441 {
442 return &sOSMetaClassMeta;
443 }
444
445 #if PRAGMA_MARK
446 #pragma mark OSMetaClass
447 #endif /* PRAGMA_MARK */
448 /*********************************************************************
449 * OSMetaClass
450 *********************************************************************/
451
452 #if APPLE_KEXT_VTABLE_PADDING
453 /*********************************************************************
454 * Reserved functions.
455 *********************************************************************/
456 void
457 OSMetaClass::_RESERVEDOSMetaClass0()
458 {
459 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0);
460 }
461 void
462 OSMetaClass::_RESERVEDOSMetaClass1()
463 {
464 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1);
465 }
466 void
467 OSMetaClass::_RESERVEDOSMetaClass2()
468 {
469 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2);
470 }
471 void
472 OSMetaClass::_RESERVEDOSMetaClass3()
473 {
474 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3);
475 }
476 void
477 OSMetaClass::_RESERVEDOSMetaClass4()
478 {
479 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4);
480 }
481 void
482 OSMetaClass::_RESERVEDOSMetaClass5()
483 {
484 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5);
485 }
486 void
487 OSMetaClass::_RESERVEDOSMetaClass6()
488 {
489 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6);
490 }
491 void
492 OSMetaClass::_RESERVEDOSMetaClass7()
493 {
494 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7);
495 }
496 #endif
497
498 /*********************************************************************
499 *********************************************************************/
500 static void
501 OSMetaClassLogErrorForKext(
502 OSReturn error,
503 OSKext * aKext)
504 {
505 const char * message = NULL;
506
507 switch (error) {
508 case kOSReturnSuccess:
509 return;
510 case kOSMetaClassNoInit: // xxx - never returned; logged at fail site
511 message = "OSMetaClass: preModLoad() wasn't called (runtime internal error).";
512 break;
513 case kOSMetaClassNoDicts:
514 message = "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries.";
515 break;
516 case kOSMetaClassNoKModSet:
517 message = "OSMetaClass: Allocation failure for internal kext recording set/set missing.";
518 break;
519 case kOSMetaClassNoInsKModSet:
520 message = "OSMetaClass: Failed to record class in kext.";
521 break;
522 case kOSMetaClassDuplicateClass:
523 message = "OSMetaClass: Duplicate class encountered.";
524 break;
525 case kOSMetaClassNoSuper: // xxx - never returned
526 message = "OSMetaClass: Can't associate a class with its superclass.";
527 break;
528 case kOSMetaClassInstNoSuper: // xxx - never returned
529 message = "OSMetaClass: Instance construction error; unknown superclass.";
530 break;
531 case kOSMetaClassNoKext:
532 message = "OSMetaClass: Kext not found for metaclass.";
533 break;
534 case kOSMetaClassInternal:
535 default:
536 message = "OSMetaClass: Runtime internal error.";
537 break;
538 }
539
540 if (message) {
541 OSKextLog(aKext, kOSMetaClassLogSpec, "%s", message);
542 }
543 return;
544 }
545
546 void
547 OSMetaClass::logError(OSReturn error)
548 {
549 OSMetaClassLogErrorForKext(error, NULL);
550 }
551
552 /*********************************************************************
553 * The core constructor for a MetaClass (defined with this name always
554 * but within the scope of its represented class).
555 *
556 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(),
557 * in between calls to OSMetaClass::preModLoad(), which sets up for
558 * registration, and OSMetaClass::postModLoad(), which actually
559 * records all the class/kext relationships of the new MetaClasses.
560 *********************************************************************/
561
562 OSMetaClass::OSMetaClass(
563 const char * inClassName,
564 const OSMetaClass * inSuperClass,
565 unsigned int inClassSize)
566 {
567 instanceCount = 0;
568 classSize = inClassSize;
569 superClassLink = inSuperClass;
570
571 reserved = IONew(ExpansionData, 1);
572 bzero(reserved, sizeof(ExpansionData));
573 #if IOTRACKING
574 uint32_t numSiteQs = 0;
575 if ((this == &OSSymbol ::gMetaClass)
576 || (this == &OSString ::gMetaClass)
577 || (this == &OSNumber ::gMetaClass)
578 || (this == &OSString ::gMetaClass)
579 || (this == &OSData ::gMetaClass)
580 || (this == &OSDictionary::gMetaClass)
581 || (this == &OSArray ::gMetaClass)
582 || (this == &OSSet ::gMetaClass)) {
583 numSiteQs = 27;
584 }
585
586 reserved->tracking = IOTrackingQueueAlloc(inClassName, (uintptr_t) this,
587 inClassSize, 0, kIOTrackingQueueTypeAlloc,
588 numSiteQs);
589 #endif
590
591 /* Hack alert: We are just casting inClassName and storing it in
592 * an OSString * instance variable. This may be because you can't
593 * create C++ objects in static constructors, but I really don't know!
594 */
595 className = (const OSSymbol *)inClassName;
596
597 // sStalledClassesLock taken in preModLoad
598 if (!sStalled) {
599 /* There's no way we can look up the kext here, unfortunately.
600 */
601 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec,
602 "OSMetaClass: preModLoad() wasn't called for class %s "
603 "(runtime internal error).",
604 inClassName);
605 } else if (!sStalled->result) {
606 // Grow stalled array if neccessary
607 if (sStalled->count >= sStalled->capacity) {
608 OSMetaClass **oldStalled = sStalled->classes;
609 int oldSize = sStalled->capacity * sizeof(OSMetaClass *);
610 int newSize = oldSize
611 + kKModCapacityIncrement * sizeof(OSMetaClass *);
612
613 sStalled->classes = (OSMetaClass **)kalloc_tag(newSize, VM_KERN_MEMORY_OSKEXT);
614 if (!sStalled->classes) {
615 sStalled->classes = oldStalled;
616 sStalled->result = kOSMetaClassNoTempData;
617 return;
618 }
619
620 sStalled->capacity += kKModCapacityIncrement;
621 memmove(sStalled->classes, oldStalled, oldSize);
622 kfree(oldStalled, oldSize);
623 OSMETA_ACCUMSIZE(((size_t)newSize) - ((size_t)oldSize));
624 }
625
626 sStalled->classes[sStalled->count++] = this;
627 }
628 }
629
630 /*********************************************************************
631 *********************************************************************/
632 OSMetaClass::~OSMetaClass()
633 {
634 OSKext * myKext = reserved ? reserved->kext : NULL; // do not release
635
636 /* Hack alert: 'className' is a C string during early C++ init, and
637 * is converted to a real OSSymbol only when we record the OSKext in
638 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext.
639 * We can't safely cast or check 'className'.
640 *
641 * Also, release className *after* calling into the kext,
642 * as removeClass() may access className.
643 */
644 IOLockLock(sAllClassesLock);
645 if (sAllClassesDict) {
646 if (myKext) {
647 sAllClassesDict->removeObject(className);
648 } else {
649 sAllClassesDict->removeObject((const char *)className);
650 }
651 }
652 IOLockUnlock(sAllClassesLock);
653
654 if (myKext) {
655 if (myKext->removeClass(this) != kOSReturnSuccess) {
656 // xxx - what can we do?
657 }
658 className->release();
659 }
660
661 // sStalledClassesLock taken in preModLoad
662 if (sStalled) {
663 unsigned int i;
664
665 /* First pass find class in stalled list. If we find it that means
666 * we started C++ init with constructors but now we're tearing down
667 * because of some failure.
668 */
669 for (i = 0; i < sStalled->count; i++) {
670 if (this == sStalled->classes[i]) {
671 break;
672 }
673 }
674
675 /* Remove this metaclass from the stalled list so postModLoad() doesn't
676 * try to register it.
677 */
678 if (i < sStalled->count) {
679 sStalled->count--;
680 if (i < sStalled->count) {
681 memmove(&sStalled->classes[i], &sStalled->classes[i + 1],
682 (sStalled->count - i) * sizeof(OSMetaClass *));
683 }
684 }
685 }
686 #if IOTRACKING
687 IOTrackingQueueFree(reserved->tracking);
688 #endif
689 IODelete(reserved, ExpansionData, 1);
690 }
691
692 /*********************************************************************
693 * Empty overrides.
694 *********************************************************************/
695 void
696 OSMetaClass::retain() const
697 {
698 }
699 void
700 OSMetaClass::release() const
701 {
702 }
703 void
704 OSMetaClass::release(__unused int when) const
705 {
706 }
707 void
708 OSMetaClass::taggedRetain(__unused const void * tag) const
709 {
710 }
711 void
712 OSMetaClass::taggedRelease(__unused const void * tag) const
713 {
714 }
715 void
716 OSMetaClass::taggedRelease(__unused const void * tag, __unused const int when) const
717 {
718 }
719 int
720 OSMetaClass::getRetainCount() const
721 {
722 return 0;
723 }
724
725 /*********************************************************************
726 *********************************************************************/
727 const char *
728 OSMetaClass::getClassName() const
729 {
730 if (!className) {
731 return NULL;
732 }
733 return className->getCStringNoCopy();
734 }
735 /*********************************************************************
736 *********************************************************************/
737 const OSSymbol *
738 OSMetaClass::getClassNameSymbol() const
739 {
740 return className;
741 }
742 /*********************************************************************
743 *********************************************************************/
744 unsigned int
745 OSMetaClass::getClassSize() const
746 {
747 return classSize;
748 }
749
750 /*********************************************************************
751 *********************************************************************/
752 void *
753 OSMetaClass::preModLoad(const char * kextIdentifier)
754 {
755 IOLockLock(sStalledClassesLock);
756
757 assert(sStalled == NULL);
758 sStalled = (StalledData *)kalloc_tag(sizeof(*sStalled), VM_KERN_MEMORY_OSKEXT);
759 if (sStalled) {
760 sStalled->classes = (OSMetaClass **)
761 kalloc_tag(kKModCapacityIncrement * sizeof(OSMetaClass *), VM_KERN_MEMORY_OSKEXT);
762 if (!sStalled->classes) {
763 kfree(sStalled, sizeof(*sStalled));
764 return NULL;
765 }
766 OSMETA_ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) +
767 sizeof(*sStalled));
768
769 sStalled->result = kOSReturnSuccess;
770 sStalled->capacity = kKModCapacityIncrement;
771 sStalled->count = 0;
772 sStalled->kextIdentifier = kextIdentifier;
773 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *));
774 }
775
776 // keep sStalledClassesLock locked until postModLoad
777
778 return sStalled;
779 }
780
781 /*********************************************************************
782 *********************************************************************/
783 bool
784 OSMetaClass::checkModLoad(void * loadHandle)
785 {
786 return sStalled && loadHandle == sStalled &&
787 sStalled->result == kOSReturnSuccess;
788 }
789
790 /*********************************************************************
791 *********************************************************************/
792 OSReturn
793 OSMetaClass::postModLoad(void * loadHandle)
794 {
795 OSReturn result = kOSReturnSuccess;
796 OSSymbol * myKextName = NULL;// must release
797 OSKext * myKext = NULL;// must release
798
799 if (!sStalled || loadHandle != sStalled) {
800 result = kOSMetaClassInternal;
801 goto finish;
802 }
803
804 if (sStalled->result) {
805 result = sStalled->result;
806 } else {
807 switch (sBootstrapState) {
808 case kNoDictionaries:
809 sBootstrapState = kMakingDictionaries;
810 // No break; fall through
811 [[clang::fallthrough]];
812
813 case kMakingDictionaries:
814 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement);
815 if (!sAllClassesDict) {
816 result = kOSMetaClassNoDicts;
817 break;
818 }
819 sAllClassesDict->setOptions(OSCollection::kSort, OSCollection::kSort);
820
821 // No break; fall through
822 [[clang::fallthrough]];
823
824 case kCompletedBootstrap:
825 {
826 unsigned int i;
827 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy(
828 sStalled->kextIdentifier));
829
830 if (!sStalled->count) {
831 break; // Nothing to do so just get out
832 }
833
834 myKext = OSKext::lookupKextWithIdentifier(myKextName);
835 if (!myKext) {
836 result = kOSMetaClassNoKext;
837
838 /* Log this error here so we can include the kext name.
839 */
840 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec,
841 "OSMetaClass: Can't record classes for kext %s - kext not found.",
842 sStalled->kextIdentifier);
843 break;
844 }
845
846 /* First pass checking classes aren't already loaded. If any already
847 * exist, we don't register any, and so we don't technically have
848 * to do any C++ teardown.
849 *
850 * Hack alert: me->className has been a C string until now.
851 * We only release the OSSymbol if we store the kext.
852 */
853 IOLockLock(sAllClassesLock);
854 for (i = 0; i < sStalled->count; i++) {
855 const OSMetaClass * me = sStalled->classes[i];
856 OSMetaClass * orig = OSDynamicCast(OSMetaClass,
857 sAllClassesDict->getObject((const char *)me->className));
858
859 if (orig) {
860 /* Log this error here so we can include the class name.
861 * xxx - we should look up the other kext that defines the class
862 */
863 #if CONFIG_EMBEDDED
864 panic(
865 #else
866 OSKextLog(myKext, kOSMetaClassLogSpec,
867 #endif /* CONFIG_EMBEDDED */
868 "OSMetaClass: Kext %s class %s is a duplicate;"
869 "kext %s already has a class by that name.",
870 sStalled->kextIdentifier, (const char *)me->className,
871 ((OSKext *)orig->reserved->kext)->getIdentifierCString());
872 result = kOSMetaClassDuplicateClass;
873 break;
874 }
875 unsigned int depth = 1;
876 while ((me = me->superClassLink)) {
877 depth++;
878 }
879 if (depth > sDeepestClass) {
880 sDeepestClass = depth;
881 }
882 }
883 IOLockUnlock(sAllClassesLock);
884
885 /* Bail if we didn't go through the entire list of new classes
886 * (if we hit a duplicate).
887 */
888 if (i != sStalled->count) {
889 break;
890 }
891
892 // Second pass symbolling strings and inserting classes in dictionary
893 IOLockLock(sAllClassesLock);
894 for (i = 0; i < sStalled->count; i++) {
895 OSMetaClass * me = sStalled->classes[i];
896
897 /* Hack alert: me->className has been a C string until now.
898 * We only release the OSSymbol in ~OSMetaClass()
899 * if we set the reference to the kext.
900 */
901 me->className =
902 OSSymbol::withCStringNoCopy((const char *)me->className);
903
904 // xxx - I suppose if these fail we're going to panic soon....
905 sAllClassesDict->setObject(me->className, me);
906
907 /* Do not retain the kext object here.
908 */
909 me->reserved->kext = myKext;
910 if (myKext) {
911 result = myKext->addClass(me, sStalled->count);
912 if (result != kOSReturnSuccess) {
913 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */
914 break;
915 }
916 }
917 }
918 IOLockUnlock(sAllClassesLock);
919 sBootstrapState = kCompletedBootstrap;
920 break;
921 }
922
923 default:
924 result = kOSMetaClassInternal;
925 break;
926 }
927 }
928
929 finish:
930 /* Don't call logError() for success or the conditions logged above
931 * or by called function.
932 */
933 if (result != kOSReturnSuccess &&
934 result != kOSMetaClassNoInsKModSet &&
935 result != kOSMetaClassDuplicateClass &&
936 result != kOSMetaClassNoKext) {
937 OSMetaClassLogErrorForKext(result, myKext);
938 }
939
940 OSSafeReleaseNULL(myKextName);
941 OSSafeReleaseNULL(myKext);
942
943 if (sStalled) {
944 OSMETA_ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) +
945 sizeof(*sStalled)));
946 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *));
947 kfree(sStalled, sizeof(*sStalled));
948 sStalled = NULL;
949 }
950
951 IOLockUnlock(sStalledClassesLock);
952
953 return result;
954 }
955
956
957 /*********************************************************************
958 *********************************************************************/
959 void
960 OSMetaClass::instanceConstructed() const
961 {
962 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink)
963 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) {
964 superClassLink->instanceConstructed();
965 }
966 }
967
968 /*********************************************************************
969 *********************************************************************/
970 void
971 OSMetaClass::instanceDestructed() const
972 {
973 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) {
974 superClassLink->instanceDestructed();
975 }
976
977 if (((int)instanceCount) < 0) {
978 OSKext * myKext = reserved->kext;
979
980 OSKextLog(myKext, kOSMetaClassLogSpec,
981 // xxx - this phrasing is rather cryptic
982 "OSMetaClass: Class %s - bad retain (%d)",
983 getClassName(), instanceCount);
984 }
985 }
986
987 /*********************************************************************
988 *********************************************************************/
989 bool
990 OSMetaClass::modHasInstance(const char * kextIdentifier)
991 {
992 bool result = false;
993 OSKext * theKext = NULL; // must release
994
995 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
996 if (!theKext) {
997 goto finish;
998 }
999
1000 result = theKext->hasOSMetaClassInstances();
1001
1002 finish:
1003 OSSafeReleaseNULL(theKext);
1004 return result;
1005 }
1006
1007 /*********************************************************************
1008 *********************************************************************/
1009 void
1010 OSMetaClass::reportModInstances(const char * kextIdentifier)
1011 {
1012 OSKext::reportOSMetaClassInstances(kextIdentifier,
1013 kOSKextLogExplicitLevel);
1014 return;
1015 }
1016 /*********************************************************************
1017 *********************************************************************/
1018
1019 void
1020 OSMetaClass::addInstance(const OSObject * instance, bool super) const
1021 {
1022 if (!super) {
1023 IOLockLock(sInstancesLock);
1024 }
1025
1026 if (!reserved->instances) {
1027 reserved->instances = OSOrderedSet::withCapacity(16);
1028 if (superClassLink) {
1029 superClassLink->addInstance(reserved->instances, true);
1030 }
1031 }
1032 reserved->instances->setLastObject(instance);
1033
1034 if (!super) {
1035 IOLockUnlock(sInstancesLock);
1036 }
1037 }
1038
1039 void
1040 OSMetaClass::removeInstance(const OSObject * instance, bool super) const
1041 {
1042 if (!super) {
1043 IOLockLock(sInstancesLock);
1044 }
1045
1046 if (reserved->instances) {
1047 reserved->instances->removeObject(instance);
1048 if (0 == reserved->instances->getCount()) {
1049 if (superClassLink) {
1050 superClassLink->removeInstance(reserved->instances, true);
1051 }
1052 IOLockLock(sAllClassesLock);
1053 reserved->instances->release();
1054 reserved->instances = NULL;
1055 IOLockUnlock(sAllClassesLock);
1056 }
1057 }
1058
1059 if (!super) {
1060 IOLockUnlock(sInstancesLock);
1061 }
1062 }
1063
1064 void
1065 OSMetaClass::applyToInstances(OSOrderedSet * set,
1066 OSMetaClassInstanceApplierFunction applier,
1067 void * context)
1068 {
1069 enum { kLocalDepth = 24 };
1070 unsigned int _nextIndex[kLocalDepth];
1071 OSOrderedSet * _sets[kLocalDepth];
1072 unsigned int * nextIndex = &_nextIndex[0];
1073 OSOrderedSet ** sets = &_sets[0];
1074 OSObject * obj;
1075 OSOrderedSet * childSet;
1076 unsigned int maxDepth;
1077 unsigned int idx;
1078 unsigned int level;
1079 bool done;
1080
1081 maxDepth = sDeepestClass;
1082 if (maxDepth > kLocalDepth) {
1083 nextIndex = IONew(typeof(nextIndex[0]), maxDepth);
1084 sets = IONew(typeof(sets[0]), maxDepth);
1085 }
1086 done = false;
1087 level = 0;
1088 idx = 0;
1089 do{
1090 while (!done && (obj = set->getObject(idx++))) {
1091 if ((childSet = OSDynamicCast(OSOrderedSet, obj))) {
1092 if (level >= maxDepth) {
1093 panic(">maxDepth");
1094 }
1095 sets[level] = set;
1096 nextIndex[level] = idx;
1097 level++;
1098 set = childSet;
1099 idx = 0;
1100 break;
1101 }
1102 done = (*applier)(obj, context);
1103 }
1104 if (!obj) {
1105 if (!done && level) {
1106 level--;
1107 set = sets[level];
1108 idx = nextIndex[level];
1109 } else {
1110 done = true;
1111 }
1112 }
1113 }while (!done);
1114 if (maxDepth > kLocalDepth) {
1115 IODelete(nextIndex, typeof(nextIndex[0]), maxDepth);
1116 IODelete(sets, typeof(sets[0]), maxDepth);
1117 }
1118 }
1119
1120 void
1121 OSMetaClass::applyToInstances(OSMetaClassInstanceApplierFunction applier,
1122 void * context) const
1123 {
1124 IOLockLock(sInstancesLock);
1125 if (reserved->instances) {
1126 applyToInstances(reserved->instances, applier, context);
1127 }
1128 IOLockUnlock(sInstancesLock);
1129 }
1130
1131 void
1132 OSMetaClass::applyToInstancesOfClassName(
1133 const OSSymbol * name,
1134 OSMetaClassInstanceApplierFunction applier,
1135 void * context)
1136 {
1137 OSMetaClass * meta;
1138 OSOrderedSet * set = NULL;
1139
1140 IOLockLock(sAllClassesLock);
1141 if (sAllClassesDict
1142 && (meta = (OSMetaClass *) sAllClassesDict->getObject(name))
1143 && (set = meta->reserved->instances)) {
1144 set->retain();
1145 }
1146 IOLockUnlock(sAllClassesLock);
1147
1148 if (!set) {
1149 return;
1150 }
1151
1152 IOLockLock(sInstancesLock);
1153 applyToInstances(set, applier, context);
1154 IOLockUnlock(sInstancesLock);
1155 set->release();
1156 }
1157
1158 /*********************************************************************
1159 *********************************************************************/
1160 void
1161 OSMetaClass::considerUnloads()
1162 {
1163 OSKext::considerUnloads();
1164 }
1165
1166 /*********************************************************************
1167 *********************************************************************/
1168 bool
1169 OSMetaClass::removeClasses(OSCollection * metaClasses)
1170 {
1171 OSCollectionIterator * classIterator;
1172 OSMetaClass * checkClass;
1173 bool result;
1174
1175 classIterator = OSCollectionIterator::withCollection(metaClasses);
1176 if (!classIterator) {
1177 return false;
1178 }
1179
1180 IOLockLock(sAllClassesLock);
1181
1182 result = false;
1183 do{
1184 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())
1185 && !checkClass->getInstanceCount()
1186 && !checkClass->reserved->retain) {
1187 }
1188 if (checkClass) {
1189 break;
1190 }
1191 classIterator->reset();
1192 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
1193 sAllClassesDict->removeObject(checkClass->className);
1194 }
1195 result = true;
1196 }while (false);
1197
1198 IOLockUnlock(sAllClassesLock);
1199 OSSafeReleaseNULL(classIterator);
1200
1201 return result;
1202 }
1203
1204
1205 /*********************************************************************
1206 *********************************************************************/
1207 const OSMetaClass *
1208 OSMetaClass::getMetaClassWithName(const OSSymbol * name)
1209 {
1210 OSMetaClass * retMeta = NULL;
1211
1212 if (!name) {
1213 return NULL;
1214 }
1215
1216 IOLockLock(sAllClassesLock);
1217 if (sAllClassesDict) {
1218 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name);
1219 }
1220 IOLockUnlock(sAllClassesLock);
1221
1222 return retMeta;
1223 }
1224
1225 /*********************************************************************
1226 *********************************************************************/
1227 const OSMetaClass *
1228 OSMetaClass::copyMetaClassWithName(const OSSymbol * name)
1229 {
1230 const OSMetaClass * meta;
1231
1232 if (!name) {
1233 return NULL;
1234 }
1235
1236 meta = NULL;
1237 IOLockLock(sAllClassesLock);
1238 if (sAllClassesDict) {
1239 meta = (OSMetaClass *) sAllClassesDict->getObject(name);
1240 if (meta) {
1241 OSIncrementAtomic(&meta->reserved->retain);
1242 }
1243 }
1244 IOLockUnlock(sAllClassesLock);
1245
1246 return meta;
1247 }
1248
1249 /*********************************************************************
1250 *********************************************************************/
1251 void
1252 OSMetaClass::releaseMetaClass() const
1253 {
1254 OSDecrementAtomic(&reserved->retain);
1255 }
1256
1257 /*********************************************************************
1258 *********************************************************************/
1259 OSObject *
1260 OSMetaClass::allocClassWithName(const OSSymbol * name)
1261 {
1262 const OSMetaClass * meta;
1263 OSObject * result;
1264
1265 result = NULL;
1266 meta = copyMetaClassWithName(name);
1267 if (meta) {
1268 result = meta->alloc();
1269 meta->releaseMetaClass();
1270 }
1271
1272 return result;
1273 }
1274
1275 /*********************************************************************
1276 *********************************************************************/
1277 OSObject *
1278 OSMetaClass::allocClassWithName(const OSString * name)
1279 {
1280 const OSSymbol * tmpKey = OSSymbol::withString(name);
1281 OSObject * result = allocClassWithName(tmpKey);
1282 tmpKey->release();
1283 return result;
1284 }
1285
1286 /*********************************************************************
1287 *********************************************************************/
1288 OSObject *
1289 OSMetaClass::allocClassWithName(const char * name)
1290 {
1291 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name);
1292 OSObject * result = allocClassWithName(tmpKey);
1293 tmpKey->release();
1294 return result;
1295 }
1296
1297
1298 /*********************************************************************
1299 *********************************************************************/
1300 OSMetaClassBase *
1301 OSMetaClass::checkMetaCastWithName(
1302 const OSSymbol * name,
1303 const OSMetaClassBase * in)
1304 {
1305 OSMetaClassBase * result = NULL;
1306
1307 const OSMetaClass * const meta = getMetaClassWithName(name);
1308
1309 if (meta) {
1310 result = meta->checkMetaCast(in);
1311 }
1312
1313 return result;
1314 }
1315
1316 /*********************************************************************
1317 *********************************************************************/
1318 OSMetaClassBase *
1319 OSMetaClass::
1320 checkMetaCastWithName(
1321 const OSString * name,
1322 const OSMetaClassBase * in)
1323 {
1324 const OSSymbol * tmpKey = OSSymbol::withString(name);
1325 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in);
1326
1327 tmpKey->release();
1328 return result;
1329 }
1330
1331 /*********************************************************************
1332 *********************************************************************/
1333 OSMetaClassBase *
1334 OSMetaClass::checkMetaCastWithName(
1335 const char * name,
1336 const OSMetaClassBase * in)
1337 {
1338 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name);
1339 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in);
1340
1341 tmpKey->release();
1342 return result;
1343 }
1344
1345 /*********************************************************************
1346 * OSMetaClass::checkMetaCast()
1347 * Check to see if the 'check' object has this object in its metaclass chain.
1348 * Returns check if it is indeed a kind of the current meta class, 0 otherwise.
1349 *
1350 * Generally this method is not invoked directly but is used to implement
1351 * the OSMetaClassBase::metaCast member function.
1352 *
1353 * See also OSMetaClassBase::metaCast
1354 *********************************************************************/
1355 OSMetaClassBase *
1356 OSMetaClass::checkMetaCast(
1357 const OSMetaClassBase * check) const
1358 {
1359 const OSMetaClass * const toMeta = this;
1360 const OSMetaClass * fromMeta;
1361
1362 for (fromMeta = check->getMetaClass();; fromMeta = fromMeta->superClassLink) {
1363 if (toMeta == fromMeta) {
1364 return const_cast<OSMetaClassBase *>(check); // Discard const
1365 }
1366 if (!fromMeta->superClassLink) {
1367 break;
1368 }
1369 }
1370
1371 return NULL;
1372 }
1373
1374 /*********************************************************************
1375 *********************************************************************/
1376 __dead2
1377 void
1378 OSMetaClass::reservedCalled(int ind) const
1379 {
1380 const char * cname = className->getCStringNoCopy();
1381 panic("%s::_RESERVED%s%d called.", cname, cname, ind);
1382 }
1383
1384 /*********************************************************************
1385 *********************************************************************/
1386 const
1387 OSMetaClass *
1388 OSMetaClass::getSuperClass() const
1389 {
1390 return superClassLink;
1391 }
1392
1393 /*********************************************************************
1394 *********************************************************************/
1395 const OSSymbol *
1396 OSMetaClass::getKmodName() const
1397 {
1398 OSKext * myKext = reserved ? reserved->kext : NULL;
1399 if (myKext) {
1400 return myKext->getIdentifier();
1401 }
1402 return OSSymbol::withCStringNoCopy("unknown");
1403 }
1404
1405 /*********************************************************************
1406 *********************************************************************/
1407 OSKext *
1408 OSMetaClass::getKext() const
1409 {
1410 return reserved ? reserved->kext : NULL;
1411 }
1412
1413 /*********************************************************************
1414 *********************************************************************/
1415 unsigned int
1416 OSMetaClass::getInstanceCount() const
1417 {
1418 return instanceCount;
1419 }
1420
1421 /*********************************************************************
1422 *********************************************************************/
1423 /* static */
1424 void
1425 OSMetaClass::printInstanceCounts()
1426 {
1427 OSCollectionIterator * classes;
1428 OSSymbol * className;
1429 OSMetaClass * meta;
1430
1431 IOLockLock(sAllClassesLock);
1432 classes = OSCollectionIterator::withCollection(sAllClassesDict);
1433 assert(classes);
1434
1435 while ((className = (OSSymbol *)classes->getNextObject())) {
1436 meta = (OSMetaClass *)sAllClassesDict->getObject(className);
1437 assert(meta);
1438
1439 printf("%24s count: %03d x 0x%03x = 0x%06x\n",
1440 className->getCStringNoCopy(),
1441 meta->getInstanceCount(),
1442 meta->getClassSize(),
1443 meta->getInstanceCount() * meta->getClassSize());
1444 }
1445 printf("\n");
1446 classes->release();
1447 IOLockUnlock(sAllClassesLock);
1448 return;
1449 }
1450
1451 /*********************************************************************
1452 *********************************************************************/
1453 OSDictionary *
1454 OSMetaClass::getClassDictionary()
1455 {
1456 panic("OSMetaClass::getClassDictionary() is obsoleted.\n");
1457 return NULL;
1458 }
1459
1460 /*********************************************************************
1461 *********************************************************************/
1462 bool
1463 OSMetaClass::serialize(__unused OSSerialize * s) const
1464 {
1465 panic("OSMetaClass::serialize(): Obsoleted\n");
1466 return false;
1467 }
1468
1469 /*********************************************************************
1470 *********************************************************************/
1471 /* static */
1472 void
1473 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary)
1474 {
1475 OSDictionary * classDict = NULL;
1476
1477 IOLockLock(sAllClassesLock);
1478
1479 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount());
1480 if (!classDict) {
1481 goto finish;
1482 }
1483
1484 do {
1485 OSCollectionIterator * classes;
1486 const OSSymbol * className;
1487
1488 classes = OSCollectionIterator::withCollection(sAllClassesDict);
1489 if (!classes) {
1490 break;
1491 }
1492
1493 while ((className = (const OSSymbol *)classes->getNextObject())) {
1494 const OSMetaClass * meta;
1495 OSNumber * count;
1496
1497 meta = (OSMetaClass *)sAllClassesDict->getObject(className);
1498 count = OSNumber::withNumber(meta->getInstanceCount(), 32);
1499 if (count) {
1500 classDict->setObject(className, count);
1501 count->release();
1502 }
1503 }
1504 classes->release();
1505
1506 serializeDictionary->setObject("Classes", classDict);
1507 } while (0);
1508
1509 finish:
1510 OSSafeReleaseNULL(classDict);
1511
1512 IOLockUnlock(sAllClassesLock);
1513
1514 return;
1515 }
1516
1517
1518 /*********************************************************************
1519 *********************************************************************/
1520
1521 #if IOTRACKING
1522
1523 void *
1524 OSMetaClass::trackedNew(size_t size)
1525 {
1526 IOTracking * mem;
1527
1528 mem = (typeof(mem))kalloc_tag_bt(size + sizeof(IOTracking), VM_KERN_MEMORY_LIBKERN);
1529 assert(mem);
1530 if (!mem) {
1531 return mem;
1532 }
1533
1534 memset(mem, 0, size + sizeof(IOTracking));
1535 mem++;
1536
1537 OSIVAR_ACCUMSIZE(size);
1538
1539 return mem;
1540 }
1541
1542 void
1543 OSMetaClass::trackedDelete(void * instance, size_t size)
1544 {
1545 IOTracking * mem = (typeof(mem))instance; mem--;
1546
1547 kfree(mem, size + sizeof(IOTracking));
1548 OSIVAR_ACCUMSIZE(-size);
1549 }
1550
1551 void
1552 OSMetaClass::trackedInstance(OSObject * instance) const
1553 {
1554 IOTracking * mem = (typeof(mem))instance; mem--;
1555
1556 return IOTrackingAdd(reserved->tracking, mem, classSize, false, VM_KERN_MEMORY_NONE);
1557 }
1558
1559 void
1560 OSMetaClass::trackedFree(OSObject * instance) const
1561 {
1562 IOTracking * mem = (typeof(mem))instance; mem--;
1563
1564 return IOTrackingRemove(reserved->tracking, mem, classSize);
1565 }
1566
1567 void
1568 OSMetaClass::trackedAccumSize(OSObject * instance, size_t size) const
1569 {
1570 IOTracking * mem = (typeof(mem))instance; mem--;
1571
1572 return IOTrackingAccumSize(reserved->tracking, mem, size);
1573 }
1574
1575 IOTrackingQueue *
1576 OSMetaClass::getTracking() const
1577 {
1578 return reserved->tracking;
1579 }
1580
1581 #endif /* IOTRACKING */