]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSMetaClass.cpp
bc67307d294282e28eb3660471414223eb746218
[apple/xnu.git] / libkern / c++ / OSMetaClass.cpp
1 /*
2 * Copyright (c) 2000-2006 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/pwr_mgt/RootDomain.h>
50 #include <IOKit/IOMessage.h>
51 #include <IOKit/IOLib.h>
52
53 __BEGIN_DECLS
54
55 #include <sys/systm.h>
56 #include <mach/mach_types.h>
57 #include <kern/locks.h>
58 #include <kern/clock.h>
59 #include <kern/thread_call.h>
60 #include <kern/host.h>
61 #include <mach/mach_interface.h>
62
63 #if PRAGMA_MARK
64 #pragma mark Macros
65 #endif /* PRAGMA_MARK */
66 /*********************************************************************
67 * Macros
68 *********************************************************************/
69 #if OSALLOCDEBUG
70 extern int debug_container_malloc_size;
71 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while (0)
72 #else
73 #define ACCUMSIZE(s)
74 #endif /* OSALLOCDEBUG */
75
76 __END_DECLS
77
78 #if PRAGMA_MARK
79 #pragma mark Internal constants & data structs
80 #endif /* PRAGMA_MARK */
81 /*********************************************************************
82 * Internal constants & data structs
83 *********************************************************************/
84 OSKextLogSpec kOSMetaClassLogSpec =
85 kOSKextLogErrorLevel |
86 kOSKextLogLoadFlag |
87 kOSKextLogKextBookkeepingFlag;
88
89 static enum {
90 kCompletedBootstrap = 0,
91 kNoDictionaries = 1,
92 kMakingDictionaries = 2
93 } sBootstrapState = kNoDictionaries;
94
95 static const int kClassCapacityIncrement = 40;
96 static const int kKModCapacityIncrement = 10;
97 static OSDictionary * sAllClassesDict;
98 IOLock * sAllClassesLock = NULL;
99
100 /*
101 * While loading a kext and running all its constructors to register
102 * all OSMetaClass classes, the classes are queued up here. Only one
103 * kext can be in flight at a time, guarded by sStalledClassesLock
104 */
105 static struct StalledData {
106 const char * kextIdentifier;
107 OSReturn result;
108 unsigned int capacity;
109 unsigned int count;
110 OSMetaClass ** classes;
111 } * sStalled;
112 IOLock * sStalledClassesLock = NULL;
113
114 #if PRAGMA_MARK
115 #pragma mark OSMetaClassBase
116 #endif /* PRAGMA_MARK */
117 /*********************************************************************
118 * OSMetaClassBase.
119 *********************************************************************/
120
121 /*********************************************************************
122 * Reserved vtable functions.
123 *********************************************************************/
124 #if SLOT_USED
125 void OSMetaClassBase::_RESERVEDOSMetaClassBase0()
126 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0); }
127 void OSMetaClassBase::_RESERVEDOSMetaClassBase1()
128 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1); }
129 void OSMetaClassBase::_RESERVEDOSMetaClassBase2()
130 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); }
131 #endif /* SLOT_USED */
132
133 // As these slots are used move them up inside the #if above
134 void OSMetaClassBase::_RESERVEDOSMetaClassBase3()
135 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); }
136 void OSMetaClassBase::_RESERVEDOSMetaClassBase4()
137 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); }
138 void OSMetaClassBase::_RESERVEDOSMetaClassBase5()
139 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); }
140 void OSMetaClassBase::_RESERVEDOSMetaClassBase6()
141 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); }
142
143 /*********************************************************************
144 * These used to be inline in the header but gcc didn't believe us
145 * Now we MUST pull the inline out at least until the compiler is
146 * repaired.
147 *
148 * Helper inlines for runtime type preprocessor macros
149 *********************************************************************/
150
151 /*********************************************************************
152 *********************************************************************/
153 OSMetaClassBase *
154 OSMetaClassBase::safeMetaCast(
155 const OSMetaClassBase * me,
156 const OSMetaClass * toType)
157 {
158 return (me)? me->metaCast(toType) : 0;
159 }
160
161 /*********************************************************************
162 *********************************************************************/
163 bool
164 OSMetaClassBase::checkTypeInst(
165 const OSMetaClassBase * inst,
166 const OSMetaClassBase * typeinst)
167 {
168 const OSMetaClass * toType = OSTypeIDInst(typeinst);
169 return typeinst && inst && (0 != inst->metaCast(toType));
170 }
171
172 /*********************************************************************
173 *********************************************************************/
174 void OSMetaClassBase::
175 initialize()
176 {
177 sAllClassesLock = IOLockAlloc();
178 sStalledClassesLock = IOLockAlloc();
179 }
180
181 /*********************************************************************
182 * If you need this slot you had better setup an IOCTL style interface.
183 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU
184 * CANT change the VTABLE size ever.
185 *********************************************************************/
186 void
187 OSMetaClassBase::_RESERVEDOSMetaClassBase7()
188 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); }
189
190 /*********************************************************************
191 *********************************************************************/
192 OSMetaClassBase::OSMetaClassBase()
193 {
194 }
195
196 /*********************************************************************
197 *********************************************************************/
198 OSMetaClassBase::~OSMetaClassBase()
199 {
200 void ** thisVTable;
201
202 thisVTable = (void **) this;
203 *thisVTable = (void *) -1UL;
204 }
205
206 /*********************************************************************
207 *********************************************************************/
208 bool
209 OSMetaClassBase::isEqualTo(const OSMetaClassBase * anObj) const
210 {
211 return this == anObj;
212 }
213
214 /*********************************************************************
215 *********************************************************************/
216 OSMetaClassBase *
217 OSMetaClassBase::metaCast(const OSMetaClass * toMeta) const
218 {
219 return toMeta->checkMetaCast(this);
220 }
221
222 /*********************************************************************
223 *********************************************************************/
224 OSMetaClassBase *
225 OSMetaClassBase::metaCast(const OSSymbol * toMetaSymb) const
226 {
227 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this);
228 }
229
230 /*********************************************************************
231 *********************************************************************/
232 OSMetaClassBase *
233 OSMetaClassBase::metaCast(const OSString * toMetaStr) const
234 {
235 const OSSymbol * tempSymb = OSSymbol::withString(toMetaStr);
236 OSMetaClassBase * ret = 0;
237 if (tempSymb) {
238 ret = metaCast(tempSymb);
239 tempSymb->release();
240 }
241 return ret;
242 }
243
244 /*********************************************************************
245 *********************************************************************/
246 OSMetaClassBase *
247 OSMetaClassBase::metaCast(const char * toMetaCStr) const
248 {
249 const OSSymbol * tempSymb = OSSymbol::withCString(toMetaCStr);
250 OSMetaClassBase * ret = 0;
251 if (tempSymb) {
252 ret = metaCast(tempSymb);
253 tempSymb->release();
254 }
255 return ret;
256 }
257
258 #if PRAGMA_MARK
259 #pragma mark OSMetaClassMeta
260 #endif /* PRAGMA_MARK */
261 /*********************************************************************
262 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass
263 *********************************************************************/
264 class OSMetaClassMeta : public OSMetaClass
265 {
266 public:
267 OSMetaClassMeta();
268 OSObject * alloc() const;
269 };
270 OSMetaClassMeta::OSMetaClassMeta()
271 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass))
272 { }
273 OSObject * OSMetaClassMeta::alloc() const { return 0; }
274
275 static OSMetaClassMeta sOSMetaClassMeta;
276
277 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta;
278 const OSMetaClass * OSMetaClass::getMetaClass() const
279 { return &sOSMetaClassMeta; }
280
281 #if PRAGMA_MARK
282 #pragma mark OSMetaClass
283 #endif /* PRAGMA_MARK */
284 /*********************************************************************
285 * OSMetaClass
286 *********************************************************************/
287
288 /*********************************************************************
289 * Reserved functions.
290 *********************************************************************/
291 void OSMetaClass::_RESERVEDOSMetaClass0()
292 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0); }
293 void OSMetaClass::_RESERVEDOSMetaClass1()
294 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1); }
295 void OSMetaClass::_RESERVEDOSMetaClass2()
296 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2); }
297 void OSMetaClass::_RESERVEDOSMetaClass3()
298 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3); }
299 void OSMetaClass::_RESERVEDOSMetaClass4()
300 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4); }
301 void OSMetaClass::_RESERVEDOSMetaClass5()
302 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5); }
303 void OSMetaClass::_RESERVEDOSMetaClass6()
304 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6); }
305 void OSMetaClass::_RESERVEDOSMetaClass7()
306 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7); }
307
308 /*********************************************************************
309 *********************************************************************/
310 static void
311 OSMetaClassLogErrorForKext(
312 OSReturn error,
313 OSKext * aKext)
314 {
315 const char * message = NULL;
316
317 switch (error) {
318 case kOSReturnSuccess:
319 return;
320 case kOSMetaClassNoInit: // xxx - never returned; logged at fail site
321 message = "OSMetaClass: preModLoad() wasn't called (runtime internal error).";
322 break;
323 case kOSMetaClassNoDicts:
324 message = "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries.";
325 break;
326 case kOSMetaClassNoKModSet:
327 message = "OSMetaClass: Allocation failure for internal kext recording set/set missing.";
328 break;
329 case kOSMetaClassNoInsKModSet:
330 message = "OSMetaClass: Failed to record class in kext.";
331 break;
332 case kOSMetaClassDuplicateClass:
333 message = "OSMetaClass: Duplicate class encountered.";
334 break;
335 case kOSMetaClassNoSuper: // xxx - never returned
336 message = "OSMetaClass: Can't associate a class with its superclass.";
337 break;
338 case kOSMetaClassInstNoSuper: // xxx - never returned
339 message = "OSMetaClass: Instance construction error; unknown superclass.";
340 break;
341 case kOSMetaClassNoKext:
342 message = "OSMetaClass: Kext not found for metaclass.";
343 break;
344 case kOSMetaClassInternal:
345 default:
346 message = "OSMetaClass: Runtime internal error.";
347 break;
348 }
349
350 if (message) {
351 OSKextLog(aKext, kOSMetaClassLogSpec, "%s", message);
352 }
353 return;
354 }
355
356 void
357 OSMetaClass::logError(OSReturn error)
358 {
359 OSMetaClassLogErrorForKext(error, NULL);
360 }
361
362 /*********************************************************************
363 * The core constructor for a MetaClass (defined with this name always
364 * but within the scope of its represented class).
365 *
366 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(),
367 * in between calls to OSMetaClass::preModLoad(), which sets up for
368 * registration, and OSMetaClass::postModLoad(), which actually
369 * records all the class/kext relationships of the new MetaClasses.
370 *********************************************************************/
371 OSMetaClass::OSMetaClass(
372 const char * inClassName,
373 const OSMetaClass * inSuperClass,
374 unsigned int inClassSize)
375 {
376 instanceCount = 0;
377 classSize = inClassSize;
378 superClassLink = inSuperClass;
379
380 /* Hack alert: We are just casting inClassName and storing it in
381 * an OSString * instance variable. This may be because you can't
382 * create C++ objects in static constructors, but I really don't know!
383 */
384 className = (const OSSymbol *)inClassName;
385
386 // sStalledClassesLock taken in preModLoad
387 if (!sStalled) {
388 /* There's no way we can look up the kext here, unfortunately.
389 */
390 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec,
391 "OSMetaClass: preModLoad() wasn't called for class %s "
392 "(runtime internal error).",
393 inClassName);
394 } else if (!sStalled->result) {
395 // Grow stalled array if neccessary
396 if (sStalled->count >= sStalled->capacity) {
397 OSMetaClass **oldStalled = sStalled->classes;
398 int oldSize = sStalled->capacity * sizeof(OSMetaClass *);
399 int newSize = oldSize
400 + kKModCapacityIncrement * sizeof(OSMetaClass *);
401
402 sStalled->classes = (OSMetaClass **)kalloc(newSize);
403 if (!sStalled->classes) {
404 sStalled->classes = oldStalled;
405 sStalled->result = kOSMetaClassNoTempData;
406 return;
407 }
408
409 sStalled->capacity += kKModCapacityIncrement;
410 memmove(sStalled->classes, oldStalled, oldSize);
411 kfree(oldStalled, oldSize);
412 ACCUMSIZE(newSize - oldSize);
413 }
414
415 sStalled->classes[sStalled->count++] = this;
416 }
417 }
418
419 /*********************************************************************
420 *********************************************************************/
421 OSMetaClass::~OSMetaClass()
422 {
423 OSKext * myKext = (OSKext *)reserved; // do not release
424
425 /* Hack alert: 'className' is a C string during early C++ init, and
426 * is converted to a real OSSymbol only when we record the OSKext in
427 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext.
428 * We can't safely cast or check 'className'.
429 *
430 * Also, release className *after* calling into the kext,
431 * as removeClass() may access className.
432 */
433 IOLockLock(sAllClassesLock);
434 if (sAllClassesDict) {
435 if (myKext) {
436 sAllClassesDict->removeObject(className);
437 } else {
438 sAllClassesDict->removeObject((char *)className);
439 }
440 }
441 IOLockUnlock(sAllClassesLock);
442
443 if (myKext) {
444 if (myKext->removeClass(this) != kOSReturnSuccess) {
445 // xxx - what can we do?
446 }
447 className->release();
448 }
449
450 // sStalledClassesLock taken in preModLoad
451 if (sStalled) {
452 unsigned int i;
453
454 /* First pass find class in stalled list. If we find it that means
455 * we started C++ init with constructors but now we're tearing down
456 * because of some failure.
457 */
458 for (i = 0; i < sStalled->count; i++) {
459 if (this == sStalled->classes[i]) {
460 break;
461 }
462 }
463
464 /* Remove this metaclass from the stalled list so postModLoad() doesn't
465 * try to register it.
466 */
467 if (i < sStalled->count) {
468 sStalled->count--;
469 if (i < sStalled->count) {
470 memmove(&sStalled->classes[i], &sStalled->classes[i+1],
471 (sStalled->count - i) * sizeof(OSMetaClass *));
472 }
473 }
474 }
475 }
476
477 /*********************************************************************
478 * Empty overrides.
479 *********************************************************************/
480 void * OSMetaClass::operator new(__unused size_t size) { return 0; }
481 void OSMetaClass::retain() const { }
482 void OSMetaClass::release() const { }
483 void OSMetaClass::release(__unused int when) const { }
484 void OSMetaClass::taggedRetain(__unused const void * tag) const { }
485 void OSMetaClass::taggedRelease(__unused const void * tag) const { }
486 void OSMetaClass::taggedRelease(__unused const void * tag, __unused const int when) const { }
487 int OSMetaClass::getRetainCount() const { return 0; }
488
489 /*********************************************************************
490 *********************************************************************/
491 const char *
492 OSMetaClass::getClassName() const
493 {
494 return className->getCStringNoCopy();
495 }
496
497 /*********************************************************************
498 *********************************************************************/
499 unsigned int
500 OSMetaClass::getClassSize() const
501 {
502 return classSize;
503 }
504
505 /*********************************************************************
506 *********************************************************************/
507 void *
508 OSMetaClass::preModLoad(const char * kextIdentifier)
509 {
510 IOLockLock(sStalledClassesLock);
511
512 assert (sStalled == NULL);
513 sStalled = (StalledData *)kalloc(sizeof(* sStalled));
514 if (sStalled) {
515 sStalled->classes = (OSMetaClass **)
516 kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *));
517 if (!sStalled->classes) {
518 kfree(sStalled, sizeof(*sStalled));
519 return 0;
520 }
521 ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) +
522 sizeof(*sStalled));
523
524 sStalled->result = kOSReturnSuccess;
525 sStalled->capacity = kKModCapacityIncrement;
526 sStalled->count = 0;
527 sStalled->kextIdentifier = kextIdentifier;
528 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *));
529 }
530
531 // keep sStalledClassesLock locked until postModLoad
532
533 return sStalled;
534 }
535
536 /*********************************************************************
537 *********************************************************************/
538 bool
539 OSMetaClass::checkModLoad(void * loadHandle)
540 {
541 return sStalled && loadHandle == sStalled &&
542 sStalled->result == kOSReturnSuccess;
543 }
544
545 /*********************************************************************
546 *********************************************************************/
547 OSReturn
548 OSMetaClass::postModLoad(void * loadHandle)
549 {
550 OSReturn result = kOSReturnSuccess;
551 OSSymbol * myKextName = 0; // must release
552 OSKext * myKext = 0; // must release
553
554 if (!sStalled || loadHandle != sStalled) {
555 result = kOSMetaClassInternal;
556 goto finish;
557 }
558
559 if (sStalled->result) {
560 result = sStalled->result;
561 } else switch (sBootstrapState) {
562
563 case kNoDictionaries:
564 sBootstrapState = kMakingDictionaries;
565 // No break; fall through
566
567 case kMakingDictionaries:
568 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement);
569 if (!sAllClassesDict) {
570 result = kOSMetaClassNoDicts;
571 break;
572 }
573
574 // No break; fall through
575
576 case kCompletedBootstrap:
577 {
578 unsigned int i;
579 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy(
580 sStalled->kextIdentifier));
581
582 if (!sStalled->count) {
583 break; // Nothing to do so just get out
584 }
585
586 myKext = OSKext::lookupKextWithIdentifier(myKextName);
587 if (!myKext) {
588 result = kOSMetaClassNoKext;
589
590 /* Log this error here so we can include the kext name.
591 */
592 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec,
593 "OSMetaClass: Can't record classes for kext %s - kext not found.",
594 sStalled->kextIdentifier);
595 break;
596 }
597
598 /* First pass checking classes aren't already loaded. If any already
599 * exist, we don't register any, and so we don't technically have
600 * to do any C++ teardown.
601 *
602 * Hack alert: me->className has been a C string until now.
603 * We only release the OSSymbol if we store the kext.
604 */
605 IOLockLock(sAllClassesLock);
606 for (i = 0; i < sStalled->count; i++) {
607 OSMetaClass * me = sStalled->classes[i];
608 OSMetaClass * orig = OSDynamicCast(OSMetaClass,
609 sAllClassesDict->getObject((const char *)me->className));
610
611 if (orig) {
612
613 /* Log this error here so we can include the class name.
614 * xxx - we should look up the other kext that defines the class
615 */
616 OSKextLog(myKext, kOSMetaClassLogSpec,
617 "OSMetaClass: Kext %s class %s is a duplicate;"
618 "kext %s already has a class by that name.",
619 sStalled->kextIdentifier, (const char *)me->className,
620 ((OSKext *)orig->reserved)->getIdentifierCString());
621 result = kOSMetaClassDuplicateClass;
622 break;
623 }
624 }
625 IOLockUnlock(sAllClassesLock);
626
627 /* Bail if we didn't go through the entire list of new classes
628 * (if we hit a duplicate).
629 */
630 if (i != sStalled->count) {
631 break;
632 }
633
634 // Second pass symbolling strings and inserting classes in dictionary
635 IOLockLock(sAllClassesLock);
636 for (i = 0; i < sStalled->count; i++) {
637 OSMetaClass * me = sStalled->classes[i];
638
639 /* Hack alert: me->className has been a C string until now.
640 * We only release the OSSymbol in ~OSMetaClass()
641 * if we set the reference to the kext.
642 */
643 me->className =
644 OSSymbol::withCStringNoCopy((const char *)me->className);
645
646 // xxx - I suppose if these fail we're going to panic soon....
647 sAllClassesDict->setObject(me->className, me);
648
649 /* Do not retain the kext object here.
650 */
651 me->reserved = (ExpansionData *)myKext;
652 if (myKext) {
653 result = myKext->addClass(me, sStalled->count);
654 if (result != kOSReturnSuccess) {
655 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */
656 break;
657 }
658 }
659 }
660 IOLockUnlock(sAllClassesLock);
661 sBootstrapState = kCompletedBootstrap;
662 break;
663 }
664
665 default:
666 result = kOSMetaClassInternal;
667 break;
668 }
669
670 finish:
671 /* Don't call logError() for success or the conditions logged above
672 * or by called function.
673 */
674 if (result != kOSReturnSuccess &&
675 result != kOSMetaClassNoInsKModSet &&
676 result != kOSMetaClassDuplicateClass &&
677 result != kOSMetaClassNoKext) {
678
679 OSMetaClassLogErrorForKext(result, myKext);
680 }
681
682 OSSafeRelease(myKextName);
683 OSSafeRelease(myKext);
684
685 if (sStalled) {
686 ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) +
687 sizeof(*sStalled)));
688 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *));
689 kfree(sStalled, sizeof(*sStalled));
690 sStalled = 0;
691 }
692
693 IOLockUnlock(sStalledClassesLock);
694
695 return result;
696 }
697
698
699 /*********************************************************************
700 *********************************************************************/
701 void
702 OSMetaClass::instanceConstructed() const
703 {
704 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink)
705 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) {
706 superClassLink->instanceConstructed();
707 }
708 }
709
710 /*********************************************************************
711 *********************************************************************/
712 void
713 OSMetaClass::instanceDestructed() const
714 {
715 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) {
716 superClassLink->instanceDestructed();
717 }
718
719 if (((int)instanceCount) < 0) {
720 OSKext * myKext = (OSKext *)reserved;
721
722 OSKextLog(myKext, kOSMetaClassLogSpec,
723 // xxx - this phrasing is rather cryptic
724 "OSMetaClass: Class %s - bad retain (%d)",
725 getClassName(), instanceCount);
726 }
727 }
728
729 /*********************************************************************
730 *********************************************************************/
731 bool
732 OSMetaClass::modHasInstance(const char * kextIdentifier)
733 {
734 bool result = false;
735 OSKext * theKext = NULL; // must release
736
737 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
738 if (!theKext) {
739 goto finish;
740 }
741
742 result = theKext->hasOSMetaClassInstances();
743
744 finish:
745 OSSafeRelease(theKext);
746 return result;
747 }
748
749 /*********************************************************************
750 *********************************************************************/
751 void
752 OSMetaClass::reportModInstances(const char * kextIdentifier)
753 {
754 OSKext::reportOSMetaClassInstances(kextIdentifier,
755 kOSKextLogExplicitLevel);
756 return;
757 }
758
759 /*********************************************************************
760 *********************************************************************/
761 void
762 OSMetaClass::considerUnloads()
763 {
764 OSKext::considerUnloads();
765 }
766
767 /*********************************************************************
768 *********************************************************************/
769 const OSMetaClass *
770 OSMetaClass::getMetaClassWithName(const OSSymbol * name)
771 {
772 OSMetaClass * retMeta = 0;
773
774 if (!name) {
775 return 0;
776 }
777
778 IOLockLock(sAllClassesLock);
779 if (sAllClassesDict) {
780 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name);
781 }
782 IOLockUnlock(sAllClassesLock);
783
784 return retMeta;
785 }
786
787 /*********************************************************************
788 *********************************************************************/
789 OSObject *
790 OSMetaClass::allocClassWithName(const OSSymbol * name)
791 {
792 OSObject * result = 0;
793
794 const OSMetaClass * const meta = getMetaClassWithName(name);
795
796 if (meta) {
797 result = meta->alloc();
798 }
799
800 return result;
801 }
802
803 /*********************************************************************
804 *********************************************************************/
805 OSObject *
806 OSMetaClass::allocClassWithName(const OSString * name)
807 {
808 const OSSymbol * tmpKey = OSSymbol::withString(name);
809 OSObject * result = allocClassWithName(tmpKey);
810 tmpKey->release();
811 return result;
812 }
813
814 /*********************************************************************
815 *********************************************************************/
816 OSObject *
817 OSMetaClass::allocClassWithName(const char * name)
818 {
819 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name);
820 OSObject * result = allocClassWithName(tmpKey);
821 tmpKey->release();
822 return result;
823 }
824
825
826 /*********************************************************************
827 *********************************************************************/
828 OSMetaClassBase *
829 OSMetaClass::checkMetaCastWithName(
830 const OSSymbol * name,
831 const OSMetaClassBase * in)
832 {
833 OSMetaClassBase * result = 0;
834
835 const OSMetaClass * const meta = getMetaClassWithName(name);
836
837 if (meta) {
838 result = meta->checkMetaCast(in);
839 }
840
841 return result;
842 }
843
844 /*********************************************************************
845 *********************************************************************/
846 OSMetaClassBase * OSMetaClass::
847 checkMetaCastWithName(
848 const OSString * name,
849 const OSMetaClassBase * in)
850 {
851 const OSSymbol * tmpKey = OSSymbol::withString(name);
852 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in);
853
854 tmpKey->release();
855 return result;
856 }
857
858 /*********************************************************************
859 *********************************************************************/
860 OSMetaClassBase *
861 OSMetaClass::checkMetaCastWithName(
862 const char * name,
863 const OSMetaClassBase * in)
864 {
865 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name);
866 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in);
867
868 tmpKey->release();
869 return result;
870 }
871
872 /*********************************************************************
873 * OSMetaClass::checkMetaCast()
874 * Check to see if the 'check' object has this object in its metaclass chain.
875 * Returns check if it is indeed a kind of the current meta class, 0 otherwise.
876 *
877 * Generally this method is not invoked directly but is used to implement
878 * the OSMetaClassBase::metaCast member function.
879 *
880 * See also OSMetaClassBase::metaCast
881 *********************************************************************/
882 OSMetaClassBase * OSMetaClass::checkMetaCast(
883 const OSMetaClassBase * check) const
884 {
885 const OSMetaClass * const toMeta = this;
886 const OSMetaClass * fromMeta;
887
888 for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) {
889 if (toMeta == fromMeta) {
890 return const_cast<OSMetaClassBase *>(check); // Discard const
891 }
892 if (!fromMeta->superClassLink) {
893 break;
894 }
895 }
896
897 return 0;
898 }
899
900 /*********************************************************************
901 *********************************************************************/
902 void
903 OSMetaClass::reservedCalled(int ind) const
904 {
905 const char * cname = className->getCStringNoCopy();
906 panic("%s::_RESERVED%s%d called.", cname, cname, ind);
907 }
908
909 /*********************************************************************
910 *********************************************************************/
911 const
912 OSMetaClass *
913 OSMetaClass::getSuperClass() const
914 {
915 return superClassLink;
916 }
917
918 /*********************************************************************
919 * xxx - I want to rename this :-/
920 *********************************************************************/
921 const OSSymbol *
922 OSMetaClass::getKmodName() const
923 {
924 OSKext * myKext = (OSKext *)reserved;
925 if (myKext) {
926 return myKext->getIdentifier();
927 }
928 return OSSymbol::withCStringNoCopy("unknown");
929 }
930
931 /*********************************************************************
932 *********************************************************************/
933 unsigned int
934 OSMetaClass::getInstanceCount() const
935 {
936 return instanceCount;
937 }
938
939 /*********************************************************************
940 *********************************************************************/
941 /* static */
942 void
943 OSMetaClass::printInstanceCounts()
944 {
945 OSCollectionIterator * classes;
946 OSSymbol * className;
947 OSMetaClass * meta;
948
949 IOLockLock(sAllClassesLock);
950 classes = OSCollectionIterator::withCollection(sAllClassesDict);
951 assert(classes);
952
953 while( (className = (OSSymbol *)classes->getNextObject())) {
954 meta = (OSMetaClass *)sAllClassesDict->getObject(className);
955 assert(meta);
956
957 printf("%24s count: %03d x 0x%03x = 0x%06x\n",
958 className->getCStringNoCopy(),
959 meta->getInstanceCount(),
960 meta->getClassSize(),
961 meta->getInstanceCount() * meta->getClassSize() );
962 }
963 printf("\n");
964 classes->release();
965 IOLockUnlock(sAllClassesLock);
966 return;
967 }
968
969 /*********************************************************************
970 *********************************************************************/
971 OSDictionary *
972 OSMetaClass::getClassDictionary()
973 {
974 panic("OSMetaClass::getClassDictionary() is obsoleted.\n");
975 return 0;
976 }
977
978 /*********************************************************************
979 *********************************************************************/
980 bool
981 OSMetaClass::serialize(__unused OSSerialize * s) const
982 {
983 panic("OSMetaClass::serialize(): Obsoleted\n");
984 return false;
985 }
986
987 /*********************************************************************
988 *********************************************************************/
989 /* static */
990 void
991 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary)
992 {
993 OSDictionary * classDict = NULL;
994
995 IOLockLock(sAllClassesLock);
996
997 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount());
998 if (!classDict) {
999 goto finish;
1000 }
1001
1002 do {
1003 OSCollectionIterator * classes;
1004 const OSSymbol * className;
1005
1006 classes = OSCollectionIterator::withCollection(sAllClassesDict);
1007 if (!classes) {
1008 break;
1009 }
1010
1011 while ((className = (const OSSymbol *)classes->getNextObject())) {
1012 const OSMetaClass * meta;
1013 OSNumber * count;
1014
1015 meta = (OSMetaClass *)sAllClassesDict->getObject(className);
1016 count = OSNumber::withNumber(meta->getInstanceCount(), 32);
1017 if (count) {
1018 classDict->setObject(className, count);
1019 count->release();
1020 }
1021 }
1022 classes->release();
1023
1024 serializeDictionary->setObject("Classes", classDict);
1025 } while (0);
1026
1027 finish:
1028 OSSafeRelease(classDict);
1029
1030 IOLockUnlock(sAllClassesLock);
1031
1032 return;
1033 }