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