|
|
1.1 root 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++/OSCollectionIterator.h>
30: #include <libkern/c++/OSDictionary.h>
31: #include <libkern/c++/OSMetaClass.h>
32: #include <libkern/c++/OSArray.h>
33: #include <libkern/c++/OSSet.h>
34: #include <libkern/c++/OSSymbol.h>
35: #include <libkern/c++/OSNumber.h>
36: #include <libkern/c++/OSSerialize.h>
37: #include <libkern/c++/OSLib.h>
38:
39: enum {
40: kSuperIsCString = 0x80000000,
41: };
42:
43: __BEGIN_DECLS
44:
45: #include <mach/etap_events.h>
46: #include <kern/lock.h>
47:
48: #ifdef DEBUG
49: extern int debug_container_malloc_size;
50: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
51: #else
52: #define ACCUMSIZE(s)
53: #endif /* DEBUG */
54:
55: __END_DECLS
56:
57: static enum {
58: kCompletedBootstrap = 0,
59: kNoDictionaries = 1,
60: kMakingDictionaries = 2
61: } sBootstrapState = kNoDictionaries;
62:
63: static const int kClassCapacityIncrement = 40;
64: static const int kKModCapacityIncrement = 10;
65: static OSDictionary *sAllClassesDict, *sKModClassesDict;
66:
67: static mutex_t *loadLock;
68: static struct StalledData {
69: const char *kmodName;
70: OSReturn result;
71: unsigned int capacity;
72: unsigned int count;
73: OSMetaClass **classes;
74: } *sStalled;
75:
76: void OSMetaClass::logError(OSReturn result)
77: {
78: const char *msg;
79:
80: switch (result) {
81: case kOSMetaClassNoInit:
82: msg="OSMetaClass::preModLoad wasn't called, runtime internal error";
83: break;
84: case kOSMetaClassNoDicts:
85: msg="Allocation failure for Metaclass internal dictionaries"; break;
86: case kOSMetaClassNoKModSet:
87: msg="Allocation failure for internal kmodule set"; break;
88: case kOSMetaClassNoInsKModSet:
89: msg="Can't insert the KMod set into the module dictionary"; break;
90: case kOSMetaClassNoSuper:
91: msg="Can't associate a class with its super class"; break;
92: case kOSMetaClassInstNoSuper:
93: msg="Instance construction, unknown super class."; break;
94: default:
95: case kOSMetaClassInternal:
96: msg="runtime internal error"; break;
97: case kOSReturnSuccess:
98: return;
99: }
100: printf("%s\n", msg);
101: }
102:
103: OSMetaClass::OSMetaClass(const char *inClassName,
104: const char *inSuperClassName,
105: unsigned int inClassSize)
106: {
107: instanceCount = 0;
108: classSize = inClassSize;
109: if (inSuperClassName && *inSuperClassName) {
110: superClass = (OSMetaClass *) inSuperClassName;
111: classSize |= kSuperIsCString;
112: }
113: else
114: superClass = 0;
115:
116: className = (const OSSymbol *) inClassName;
117:
118: if (!sStalled) {
119: printf("OSMetaClass::preModLoad wasn't called for %s, "
120: "runtime internal error\n", inClassName);
121: } else if (!sStalled->result) {
122: // Grow stalled array if neccessary
123: if (sStalled->count >= sStalled->capacity) {
124: OSMetaClass **oldStalled = sStalled->classes;
125: int oldSize = sStalled->capacity * sizeof(OSMetaClass *);
126: int newSize = oldSize
127: + kKModCapacityIncrement * sizeof(OSMetaClass *);
128:
129: sStalled->classes = (OSMetaClass **) kalloc(newSize);
130: if (!sStalled->classes) {
131: sStalled->classes = oldStalled;
132: sStalled->result = kOSMetaClassNoTempData;
133: return;
134: }
135:
136: sStalled->capacity += kKModCapacityIncrement;
137: memmove(sStalled->classes, oldStalled, oldSize);
138: kfree((vm_offset_t)oldStalled, oldSize);
139: ACCUMSIZE(newSize - oldSize);
140: }
141:
142: sStalled->classes[sStalled->count++] = this;
143: }
144: }
145:
146: OSMetaClass::~OSMetaClass()
147: {
148: do {
149: OSCollectionIterator *iter;
150:
151: if (sAllClassesDict)
152: sAllClassesDict->removeObject(className);
153:
154: iter = OSCollectionIterator::withCollection(sKModClassesDict);
155: if (!iter)
156: break;
157:
158: OSSymbol *iterKey;
159: while ( (iterKey = (OSSymbol *) iter->getNextObject()) ) {
160: OSSet *kmodClassSet;
161: kmodClassSet = (OSSet *) sKModClassesDict->getObject(iterKey);
162: if (kmodClassSet && kmodClassSet->containsObject(this)) {
163: kmodClassSet->removeObject(this);
164: break;
165: }
166: }
167: iter->release();
168: } while (false);
169:
170: if (sStalled) {
171: unsigned int i;
172:
173: // First pass find class in stalled list
174: for (i = 0; i < sStalled->count; i++)
175: if (this == sStalled->classes[i])
176: break;
177:
178: if (i < sStalled->count) {
179: sStalled->count--;
180: if (i < sStalled->count)
181: memmove(&sStalled->classes[i], &sStalled->classes[i+1],
182: (sStalled->count - i) * sizeof(OSMetaClass *));
183: }
184: return;
185: }
186: }
187:
188: // Don't do anything as these classes must be statically allocated
189: void OSMetaClass::free() { }
190: void OSMetaClass::retain() { }
191: void OSMetaClass::release() { }
192:
193: const char *OSMetaClass::getClassName() const
194: {
195: return className->getCStringNoCopy();
196: }
197:
198: unsigned int OSMetaClass::getClassSize() const
199: {
200: return classSize & ~kSuperIsCString;
201: }
202:
203: void *OSMetaClass::preModLoad(const char *kmodName)
204: {
205: if (!loadLock) {
206: loadLock = mutex_alloc(ETAP_IO_AHA);
207: _mutex_lock(loadLock);
208: }
209: else
210: _mutex_lock(loadLock);
211:
212: sStalled = (StalledData *) kalloc(sizeof(*sStalled));
213: if (sStalled) {
214: sStalled->classes = (OSMetaClass **)
215: kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *));
216: if (!sStalled->classes) {
217: kfree((vm_offset_t) sStalled, sizeof(*sStalled));
218: return 0;
219: }
220: ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled));
221:
222: sStalled->result = kOSReturnSuccess;
223: sStalled->capacity = kKModCapacityIncrement;
224: sStalled->count = 0;
225: sStalled->kmodName = kmodName;
226: bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *));
227: }
228:
229: return sStalled;
230: }
231:
232: bool OSMetaClass::checkModLoad(void *loadHandle)
233: {
234: return sStalled && loadHandle == sStalled
235: && sStalled->result == kOSReturnSuccess;
236: }
237:
238: static inline const OSSymbol *copySymbol(bool copy, const char *cString)
239: {
240: if (copy)
241: return OSSymbol::withCString(cString);
242: else
243: return OSSymbol::withCStringNoCopy(cString);
244: }
245:
246: OSReturn OSMetaClass::postModLoad(void *loadHandle)
247: {
248: OSReturn result = kOSReturnSuccess;
249: OSSet *kmodSet = 0;
250:
251: if (!sStalled || loadHandle != sStalled) {
252: logError(kOSMetaClassInternal);
253: return kOSMetaClassInternal;
254: }
255:
256: if (sStalled->result)
257: result = sStalled->result;
258: else switch (sBootstrapState) {
259: case kNoDictionaries:
260: sBootstrapState = kMakingDictionaries;
261: // No break; fall through
262:
263: case kMakingDictionaries:
264: sKModClassesDict = OSDictionary::withCapacity(kKModCapacityIncrement);
265: sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement);
266: if (!sAllClassesDict || !sKModClassesDict) {
267: result = kOSMetaClassNoDicts;
268: break;
269: }
270: // No break; fall through
271:
272: case kCompletedBootstrap:
273: {
274: bool copyStrings = (0 != strcmp("__kernel__", sStalled->kmodName));
275:
276: if (!sStalled->count)
277: break; // Nothing to do so just get out
278:
279: kmodSet = OSSet::withCapacity(sStalled->count);
280: if (!kmodSet) {
281: result = kOSMetaClassNoKModSet;
282: break;
283: }
284:
285: if (!sKModClassesDict->setObject(sStalled->kmodName, kmodSet)) {
286: result = kOSMetaClassNoInsKModSet;
287: break;
288: }
289:
290: // First pass symbolling strings and inserting classes in dictionary
291: for (unsigned int i = 0; i < sStalled->count; i++) {
292: OSMetaClass *me = sStalled->classes[i];
293:
294: me->className = copySymbol(copyStrings,
295: (const char *) me->className);
296: if (me->classSize & kSuperIsCString)
297: me->superClass = (OSMetaClass *)
298: copySymbol(copyStrings, (const char *) me->superClass);
299:
300: sAllClassesDict->setObject(me->className, me);
301: kmodSet->setObject(me);
302: }
303:
304: // Second pass to connect up superclasses.
305: for (unsigned int i = 0; !result && i < sStalled->count; i++) {
306: OSMetaClass *me = sStalled->classes[i];
307: OSSymbol *superSym;
308:
309: if (me->classSize & kSuperIsCString) {
310:
311: me->classSize &= ~kSuperIsCString;
312: superSym = (OSSymbol *) me->superClass;
313: me->superClass = (OSMetaClass *)
314: sAllClassesDict->getObject(superSym);
315: superSym->release();
316: if (!me->superClass)
317: result = kOSMetaClassNoSuper;
318: }
319: }
320: sBootstrapState = kCompletedBootstrap;
321: break;
322: }
323:
324: default:
325: result = kOSMetaClassInternal;
326: break;
327: }
328:
329: if (kmodSet)
330: kmodSet->release();
331:
332: if (sStalled) {
333: ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *)
334: + sizeof(*sStalled)));
335: kfree((vm_offset_t) sStalled->classes,
336: sStalled->capacity * sizeof(OSMetaClass *));
337: kfree((vm_offset_t) sStalled, sizeof(*sStalled));
338: sStalled = 0;
339: }
340:
341: logError(result);
342: mutex_unlock(loadLock);
343: return result;
344: }
345:
346:
347: void OSMetaClass::instanceConstructed() const
348: {
349: if (sStalled && (classSize & kSuperIsCString) && superClass)
350: {
351: OSMetaClass *me = (OSMetaClass *) this; // overide const this
352: const char * const superName = (const char *) superClass;
353:
354: // The superClass may be in the class dictionary already.
355: if (sBootstrapState == kCompletedBootstrap && sAllClassesDict)
356: me->superClass = (OSMetaClass *)
357: sAllClassesDict->getObject(superName);
358: else
359: me->superClass = 0;
360:
361: if (!me->superClass) {
362: // Oh dear we have to scan the stalled list and walk the
363: // the super class chain manually.
364: unsigned int i;
365:
366: // find superclass in stalled list
367: for (i = 0; i < sStalled->count; i++) {
368: if (0 == strcmp(superName,
369: (const char *) sStalled->classes[i]->className))
370: break;
371: }
372:
373: if (i < sStalled->count) {
374: me->superClass = sStalled->classes[i];
375: me->classSize &= ~kSuperIsCString;
376: }
377: else
378: sStalled->result = kOSMetaClassInstNoSuper;
379:
380: }
381: }
382:
383: if ((0 == instanceCount++) && superClass)
384: superClass->instanceConstructed();
385: }
386:
387: void OSMetaClass::instanceDestructed() const
388: {
389: if ((1 == instanceCount--) && superClass)
390: superClass->instanceDestructed();
391:
392: if( ((int) instanceCount) < 0)
393: printf("%s: bad retain(%d)", getClassName(), instanceCount);
394: }
395:
396: bool OSMetaClass::modHasInstance(const char *kmodName)
397: {
398: bool result = false;
399:
400: if (!loadLock) {
401: loadLock = mutex_alloc(ETAP_IO_AHA);
402: _mutex_lock(loadLock);
403: }
404: else
405: _mutex_lock(loadLock);
406:
407: do {
408: OSSet *kmodClasses;
409: OSCollectionIterator *iter;
410: OSMetaClass *checkClass;
411:
412: kmodClasses = OSDynamicCast(OSSet,
413: sKModClassesDict->getObject(kmodName));
414: if (!kmodClasses)
415: break;
416:
417: iter = OSCollectionIterator::withCollection(kmodClasses);
418: if (!iter)
419: break;
420:
421: while ( (checkClass = (OSMetaClass *) iter->getNextObject()) )
422: if (checkClass->getInstanceCount()) {
423: result = true;
424: break;
425: }
426:
427: iter->release();
428: } while (false);
429:
430: mutex_unlock(loadLock);
431:
432: return result;
433: }
434:
435: void OSMetaClass::reportModInstances(const char *kmodName)
436: {
437: OSSet *kmodClasses;
438: OSCollectionIterator *iter;
439: OSMetaClass *checkClass;
440:
441: kmodClasses = OSDynamicCast(OSSet,
442: sKModClassesDict->getObject(kmodName));
443: if (!kmodClasses)
444: return;
445:
446: iter = OSCollectionIterator::withCollection(kmodClasses);
447: if (!iter)
448: return;
449:
450: while ( (checkClass = (OSMetaClass *) iter->getNextObject()) )
451: if (checkClass->getInstanceCount()) {
452: printf("%s: %s has %d instance(s)\n",
453: kmodName,
454: checkClass->getClassName(),
455: checkClass->getInstanceCount());
456: }
457:
458: iter->release();
459: }
460:
461: const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSSymbol *name)
462: {
463: OSMetaClass *retMeta = 0;
464:
465: if (!name)
466: return 0;
467:
468: if (sAllClassesDict)
469: retMeta = (OSMetaClass *) sAllClassesDict->getObject(name);
470:
471: if (!retMeta && sStalled)
472: {
473: // Oh dear we have to scan the stalled list and walk the
474: // the stalled list manually.
475: const char *cName = name->getCStringNoCopy();
476: unsigned int i;
477:
478: // find class in stalled list
479: for (i = 0; i < sStalled->count; i++) {
480: retMeta = sStalled->classes[i];
481: if (0 == strcmp(cName, (const char *) retMeta->className))
482: break;
483: }
484:
485: if (i < sStalled->count)
486: retMeta = 0;
487: }
488:
489: return retMeta;
490: }
491:
492: const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSString *name)
493: {
494: const OSSymbol *tmpKey = OSSymbol::withString(name);
495: const OSMetaClass *ret = getMetaClassWithName(tmpKey);
496:
497: tmpKey->release();
498: return ret;
499: }
500:
501: const OSMetaClass *OSMetaClass::getMetaClassWithName(const char *name)
502: {
503: const OSSymbol *tmpKey = OSSymbol::withCStringNoCopy(name);
504: const OSMetaClass *ret = getMetaClassWithName(tmpKey);
505:
506: tmpKey->release();
507: return ret;
508: }
509:
510: OSObject *OSMetaClass::allocClassWithName(const OSSymbol *name)
511: {
512: const OSMetaClass * const meta = getMetaClassWithName(name);
513:
514: if (meta)
515: return meta->alloc();
516:
517: return 0;
518: }
519:
520: OSObject *OSMetaClass::allocClassWithName(const OSString *name)
521: {
522: const OSMetaClass * const meta = getMetaClassWithName(name);
523:
524: if (meta)
525: return meta->alloc();
526:
527: return 0;
528: }
529:
530: OSObject *OSMetaClass::allocClassWithName(const char *name)
531: {
532: const OSMetaClass * const meta = getMetaClassWithName(name);
533:
534: if (meta)
535: return meta->alloc();
536:
537: return 0;
538: }
539:
540:
541: OSObject *
542: OSMetaClass::checkMetaCastWithName(const OSSymbol *name, const OSObject *in)
543: {
544: const OSMetaClass * const meta = getMetaClassWithName(name);
545:
546: if (meta)
547: return meta->checkMetaCast(in);
548:
549: return 0;
550: }
551:
552: OSObject *
553: OSMetaClass::checkMetaCastWithName(const OSString *name, const OSObject *in)
554: {
555: const OSMetaClass * const meta = getMetaClassWithName(name);
556:
557: if (meta)
558: return meta->checkMetaCast(in);
559:
560: return 0;
561: }
562:
563: OSObject *
564: OSMetaClass::checkMetaCastWithName(const char *name, const OSObject *in)
565: {
566: const OSMetaClass * const meta = getMetaClassWithName(name);
567:
568: if (meta)
569: return meta->checkMetaCast(in);
570:
571: return 0;
572: }
573:
574: /*
575: OSMetaClass::checkMetaCast
576: checkMetaCast(OSObject *check)
577:
578: 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.
579:
580: Generally this method is not invoked directly but is used to implement the OSObject::metaCast member function.
581:
582: See also OSObject::metaCast
583:
584: */
585: OSObject *OSMetaClass::checkMetaCast(const OSObject *check) const
586: {
587: const OSMetaClass * const toMeta = this;
588: const OSMetaClass *fromMeta;
589:
590: for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClass) {
591: if (toMeta == fromMeta)
592: return (OSObject *) check; // Discard const
593:
594: if (!fromMeta->superClass || (fromMeta->classSize & kSuperIsCString))
595: break;
596: }
597:
598: return 0;
599: }
600:
601: const OSMetaClass *OSMetaClass::getSuperClass() const
602: {
603: return superClass;
604: }
605:
606: unsigned int OSMetaClass::getInstanceCount() const
607: {
608: return instanceCount;
609: }
610:
611: void OSMetaClass::printInstanceCounts()
612: {
613: OSCollectionIterator *classes;
614: OSSymbol *className;
615: OSMetaClass *meta;
616:
617: classes = OSCollectionIterator::withCollection(sAllClassesDict);
618: if (!classes)
619: return;
620:
621: while( (className = (OSSymbol *)classes->getNextObject())) {
622: meta = (OSMetaClass *) sAllClassesDict->getObject(className);
623: assert(meta);
624:
625: printf("%24s count: %03d x 0x%03x = 0x%06x\n",
626: className->getCStringNoCopy(),
627: meta->getInstanceCount(),
628: meta->getClassSize(),
629: meta->getInstanceCount() * meta->getClassSize() );
630: }
631: printf("\n");
632: classes->release();
633: }
634:
635: OSDictionary * OSMetaClass::getClassDictionary()
636: {
637: return sAllClassesDict;
638: }
639:
640: bool OSMetaClass::serialize(OSSerialize *s) const
641: {
642: OSDictionary * dict;
643: OSNumber * off;
644: bool ok = false;
645:
646: if (s->previouslySerialized(this)) return true;
647:
648: dict = 0;// IODictionary::withCapacity(2);
649: off = OSNumber::withNumber(getInstanceCount(), 32);
650:
651: if (dict) {
652: dict->setObject("InstanceCount", off );
653: ok = dict->serialize(s);
654: } else if( off)
655: ok = off->serialize(s);
656:
657: if (dict)
658: dict->release();
659: if (off)
660: off->release();
661:
662: return ok;
663: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.