1 /* 2 * Copyright (c) 2000 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* OSObject.cpp created by gvdl on Fri 1998-11-17 */ 29 30 #include <libkern/c++/OSObject.h> 31 #include <libkern/c++/OSString.h> 32 #include <libkern/c++/OSArray.h> 33 #include <libkern/c++/OSSerialize.h> 34 #include <libkern/c++/OSLib.h> 35 #include <libkern/OSDebug.h> 36 #include <libkern/c++/OSCPPDebug.h> 37 #include <IOKit/IOKitDebug.h> 38 #include <libkern/OSAtomic.h> 39 40 #include <libkern/c++/OSCollection.h> 41 42 #include <kern/queue.h> 43 44 __BEGIN_DECLS 45 int debug_ivars_size; 46 __END_DECLS 47 48 49 // OSDefineMetaClassAndAbstractStructors(OSObject, 0); 50 /* Class global data */ 51 OSObject::MetaClass OSObject::gMetaClass; 52 const OSMetaClass * const OSObject::metaClass = &OSObject::gMetaClass; 53 const OSMetaClass * const OSObject::superClass = 0; 54 55 /* Class member functions - Can't use defaults */ 56 OSObject::~OSObject() { } 57 const OSMetaClass * OSObject::getMetaClass() const 58 { return &gMetaClass; } 59 OSObject *OSObject::MetaClass::alloc() const { return 0; } 60 61 /* The OSObject::MetaClass constructor */ 62 OSObject::MetaClass::MetaClass() 63 : OSMetaClass("OSObject", OSObject::superClass, sizeof(OSObject)) 64 { } 65 66 // Virtual Padding 67 OSMetaClassDefineReservedUnused(OSObject, 0); 68 OSMetaClassDefineReservedUnused(OSObject, 1); 69 OSMetaClassDefineReservedUnused(OSObject, 2); 70 OSMetaClassDefineReservedUnused(OSObject, 3); 71 OSMetaClassDefineReservedUnused(OSObject, 4); 72 OSMetaClassDefineReservedUnused(OSObject, 5); 73 OSMetaClassDefineReservedUnused(OSObject, 6); 74 OSMetaClassDefineReservedUnused(OSObject, 7); 75 OSMetaClassDefineReservedUnused(OSObject, 8); 76 OSMetaClassDefineReservedUnused(OSObject, 9); 77 OSMetaClassDefineReservedUnused(OSObject, 10); 78 OSMetaClassDefineReservedUnused(OSObject, 11); 79 OSMetaClassDefineReservedUnused(OSObject, 12); 80 OSMetaClassDefineReservedUnused(OSObject, 13); 81 OSMetaClassDefineReservedUnused(OSObject, 14); 82 OSMetaClassDefineReservedUnused(OSObject, 15); 83 84 static const char *getClassName(const OSObject *obj) 85 { 86 const OSMetaClass *meta = obj->getMetaClass(); 87 return (meta) ? meta->getClassName() : "unknown class?"; 88 } 89 90 int OSObject::getRetainCount() const 91 { 92 return (int) ((UInt16) retainCount); 93 } 94 95 void OSObject::taggedRetain(const void *tag) const 96 { 97 volatile UInt32 *countP = (volatile UInt32 *) &retainCount; 98 UInt32 inc = 1; 99 UInt32 origCount; 100 UInt32 newCount; 101 102 // Increment the collection bucket. 103 if ((const void *) OSTypeID(OSCollection) == tag) 104 inc |= (1UL<<16); 105 106 do { 107 origCount = *countP; 108 if ( ((UInt16) origCount | 0x1) == 0xffff ) { 109 const char *msg; 110 if (origCount & 0x1) { 111 // If count == 0xffff that means we are freeing now so we can 112 // just return obviously somebody is cleaning up dangling 113 // references. 114 msg = "Attempting to retain a freed object"; 115 } 116 else { 117 // If count == 0xfffe then we have wrapped our reference count. 118 // We should stop counting now as this reference must be 119 // leaked rather than accidently wrapping around the clock and 120 // freeing a very active object later. 121 122 #if !DEBUG 123 break; // Break out of update loop which pegs the reference 124 #else /* DEBUG */ 125 // @@@ gvdl: eventually need to make this panic optional 126 // based on a boot argument i.e. debug= boot flag 127 msg = "About to wrap the reference count, reference leak?"; 128 #endif /* !DEBUG */ 129 } 130 panic("OSObject::refcount: %s", msg); 131 } 132 133 newCount = origCount + inc; 134 } while (!OSCompareAndSwap(origCount, newCount, const_cast<UInt32 *>(countP))); 135 } 136 137 void OSObject::taggedRelease(const void *tag) const 138 { 139 taggedRelease(tag, 1); 140 } 141 142 void OSObject::taggedRelease(const void *tag, const int when) const 143 { 144 volatile UInt32 *countP = (volatile UInt32 *) &retainCount; 145 UInt32 dec = 1; 146 UInt32 origCount; 147 UInt32 newCount; 148 UInt32 actualCount; 149 150 // Increment the collection bucket. 151 if ((const void *) OSTypeID(OSCollection) == tag) 152 dec |= (1UL<<16); 153 154 do { 155 origCount = *countP; 156 157 if ( ((UInt16) origCount | 0x1) == 0xffff ) { 158 if (origCount & 0x1) { 159 // If count == 0xffff that means we are freeing now so we can 160 // just return obviously somebody is cleaning up some dangling 161 // references. So we blow out immediately. 162 return; 163 } 164 else { 165 // If count == 0xfffe then we have wrapped our reference 166 // count. We should stop counting now as this reference must be 167 // leaked rather than accidently freeing an active object later. 168 169 #if !DEBUG 170 return; // return out of function which pegs the reference 171 #else /* DEBUG */ 172 // @@@ gvdl: eventually need to make this panic optional 173 // based on a boot argument i.e. debug= boot flag 174 panic("OSObject::refcount: %s", 175 "About to unreference a pegged object, reference leak?"); 176 #endif /* !DEBUG */ 177 } 178 } 179 actualCount = origCount - dec; 180 if ((UInt16) actualCount < when) 181 newCount = 0xffff; 182 else 183 newCount = actualCount; 184 185 } while (!OSCompareAndSwap(origCount, newCount, const_cast<UInt32 *>(countP))); 186 187 // 188 // This panic means that we have just attempted to release an object 189 // whose retain count has gone to less than the number of collections 190 // it is a member off. Take a panic immediately. 191 // In fact the panic MAY not be a registry corruption but it is 192 // ALWAYS the wrong thing to do. I call it a registry corruption 'cause 193 // the registry is the biggest single use of a network of collections. 194 // 195 // xxx - this error message is overly-specific; 196 // xxx - any code in the kernel could trip this, 197 // xxx - and it applies as noted to all collections, not just the registry 198 if ((UInt16) actualCount < (actualCount >> 16)) { 199 panic("A kext releasing a(n) %s has corrupted the registry.", 200 getClassName(this)); 201 } 202 203 // Check for a 'free' condition and that if we are first through 204 if (newCount == 0xffff) { 205 (const_cast<OSObject *>(this))->free(); 206 } 207 } 208 209 void OSObject::release() const 210 { 211 taggedRelease(0); 212 } 213 214 void OSObject::retain() const 215 { 216 taggedRetain(0); 217 } 218 219 void OSObject::release(int when) const 220 { 221 taggedRelease(0, when); 222 } 223 224 bool OSObject::serialize(OSSerialize *s) const 225 { 226 char cstr[128]; 227 bool ok; 228 229 snprintf(cstr, sizeof(cstr), "%s is not serializable", getClassName(this)); 230 231 OSString * str; 232 str = OSString::withCStringNoCopy(cstr); 233 if (!str) return false; 234 235 ok = str->serialize(s); 236 str->release(); 237 238 return (ok); 239 } 240 241 void *OSObject::operator new(size_t size) 242 { 243 #if IOTRACKING 244 if (kIOTracking & gIOKitDebug) return (OSMetaClass::trackedNew(size)); 245 #endif 246 247 void * mem = kalloc_tag_bt(size, VM_KERN_MEMORY_LIBKERN); 248 assert(mem); 249 bzero(mem, size); 250 OSIVAR_ACCUMSIZE(size); 251 252 return (void *) mem; 253 } 254 255 void OSObject::operator delete(void * mem, size_t size) 256 { 257 if (!mem) return; 258 259 #if IOTRACKING 260 if (kIOTracking & gIOKitDebug) return (OSMetaClass::trackedDelete(mem, size)); 261 #endif 262 263 kfree(mem, size); 264 OSIVAR_ACCUMSIZE(-size); 265 } 266 267 bool OSObject::init() 268 { 269 #if IOTRACKING 270 if (kIOTracking & gIOKitDebug) getMetaClass()->trackedInstance(this); 271 #endif 272 return true; 273 } 274 275 void OSObject::free() 276 { 277 const OSMetaClass *meta = getMetaClass(); 278 279 if (meta) 280 { 281 meta->instanceDestructed(); 282 #if IOTRACKING 283 if (kIOTracking & gIOKitDebug) getMetaClass()->trackedFree(this); 284 #endif 285 } 286 delete this; 287 } 288 289 #if IOTRACKING 290 void OSObject::trackingAccumSize(size_t size) 291 { 292 if (kIOTracking & gIOKitDebug) getMetaClass()->trackedAccumSize(this, size); 293 } 294 #endif 295 296 /* Class member functions - Can't use defaults */ 297 /* During constructor vtable is always OSObject's - can't call any subclass */ 298 299 OSObject::OSObject() 300 { 301 retainCount = 1; 302 // if (kIOTracking & gIOKitDebug) getMetaClass()->trackedInstance(this); 303 } 304 305 OSObject::OSObject(const OSMetaClass *) 306 { 307 retainCount = 1; 308 // if (kIOTracking & gIOKitDebug) getMetaClass()->trackedInstance(this); 309 } 310