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