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