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