1/* 2 * IOFWUserObjectExporter.cpp 3 * IOFireWireFamily 4 * 5 * Created by Niels on Mon Apr 14 2003. 6 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 7 * 8 * $Log: IOFWUserObjectExporter.cpp,v $ 9 * Revision 1.19 2008/05/08 02:33:21 collin 10 * more K64 11 * 12 * Revision 1.18 2008/05/06 03:26:57 collin 13 * more K64 14 * 15 * Revision 1.17 2008/04/30 03:02:13 collin 16 * publicize the exporter 17 * 18 * Revision 1.16 2008/04/11 00:52:37 collin 19 * some K64 changes 20 * 21 * Revision 1.15 2007/03/14 01:01:12 collin 22 * *** empty log message *** 23 * 24 * Revision 1.14 2006/02/09 00:21:51 niels 25 * merge chardonnay branch to tot 26 * 27 * Revision 1.13 2005/09/24 00:55:28 niels 28 * *** empty log message *** 29 * 30 * Revision 1.12 2005/04/12 20:09:13 niels 31 * fix memory leak importing NuDCL programs from user space 32 * 33 * Revision 1.11 2005/04/02 02:43:46 niels 34 * exporter works outside IOFireWireFamily 35 * 36 * Revision 1.10 2005/03/31 02:31:44 niels 37 * more object exporter fixes 38 * 39 * Revision 1.9 2005/03/30 22:14:55 niels 40 * Fixed compile errors see on Tiger w/ GCC 4.0 41 * Moved address-of-member-function calls to use OSMemberFunctionCast 42 * Added owner field to IOFWUserObjectExporter 43 * User client now cleans up published unit directories when client dies 44 * 45 * Revision 1.8.18.3 2006/01/31 04:49:50 collin 46 * *** empty log message *** 47 * 48 * Revision 1.8.18.1 2005/07/23 00:30:44 collin 49 * *** empty log message *** 50 * 51 * Revision 1.8 2003/12/18 00:08:12 niels 52 * fix panic calling methods on deallocated user objects 53 * 54 * Revision 1.7 2003/12/15 23:31:32 niels 55 * fix object exporter panic when passed NULL object handle 56 * 57 * Revision 1.6 2003/11/20 21:32:58 niels 58 * fix radar 3490815 59 * 60 * Revision 1.5 2003/08/30 00:16:44 collin 61 * *** empty log message *** 62 * 63 * Revision 1.4 2003/08/27 19:27:04 niels 64 * *** empty log message *** 65 * 66 * Revision 1.3 2003/08/08 22:30:32 niels 67 * *** empty log message *** 68 * 69 * Revision 1.2 2003/07/21 06:52:59 niels 70 * merge isoch to TOT 71 * 72 * Revision 1.1.2.1 2003/07/01 20:54:07 niels 73 * isoch merge 74 * 75 */ 76 77#undef min 78#undef max 79 80#import <sys/systm.h> // for snprintf... 81 82#import "IOFWUserObjectExporter.h" 83#import "FWDebugging.h" 84 85#undef super 86#define super OSObject 87 88OSDefineMetaClassAndStructors ( IOFWUserObjectExporter, super ); 89 90OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 0); 91OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 1); 92OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 2); 93OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 3); 94OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 4); 95OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 5); 96OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 6); 97OSMetaClassDefineReservedUnused(IOFWUserObjectExporter, 7); 98 99// createWithOwner 100// 101// static factory method 102 103IOFWUserObjectExporter * IOFWUserObjectExporter::createWithOwner( OSObject * owner ) 104{ 105 DebugLog( "IOFWUserObjectExporter::create\n" ); 106 107 bool success = true; 108 109 IOFWUserObjectExporter * object = NULL; 110 111 object = OSTypeAlloc( IOFWUserObjectExporter ); 112 if( object == NULL ) 113 { 114 success = false; 115 } 116 117 if( success ) 118 { 119 success = object->initWithOwner( owner ); 120 } 121 122 if( !success ) 123 { 124 if( object ) 125 { 126 object->release(); 127 object = NULL; 128 } 129 } 130 131 return object; 132} 133 134bool 135IOFWUserObjectExporter::init() 136{ 137 fLock = IOLockAlloc () ; 138 if ( ! fLock ) 139 return false ; 140 141 return super::init () ; 142} 143 144bool 145IOFWUserObjectExporter::initWithOwner ( OSObject * owner ) 146{ 147 fOwner = owner ; 148 149 return init() ; 150} 151 152void 153IOFWUserObjectExporter::free () 154{ 155 DebugLog( "free object exporter %p, fObjectCount = %d\n", this, fObjectCount ) ; 156 157 removeAllObjects () ; 158 159 if ( fLock ) 160 IOLockFree( fLock ) ; 161 162 fOwner = NULL ; 163 164 super::free () ; 165} 166 167bool 168IOFWUserObjectExporter::serialize ( 169 OSSerialize * s ) const 170{ 171 lock() ; 172 173 const OSString * keys[ 3 ] = 174 { 175 OSString::withCString( "capacity" ) 176 , OSString::withCString( "used" ) 177 , OSString::withCString( "objects" ) 178 } ; 179 180 const OSObject * objects[ 3 ] = 181 { 182 OSNumber::withNumber( (unsigned long long)fCapacity, 32 ) 183 , OSNumber::withNumber( (unsigned long long)fObjectCount, 32 ) 184 , fObjects ? OSArray::withObjects( fObjects, fObjectCount ) : OSArray::withCapacity(0) 185 } ; 186 187 OSDictionary * dict = OSDictionary::withObjects( objects, keys, sizeof( keys ) / sizeof( OSObject* ) ) ; 188 189 if ( !dict ) 190 { 191 unlock() ; 192 return false ; 193 } 194 195 bool result = dict->serialize( s ) ; 196 197 unlock() ; 198 199 return result ; 200} 201 202IOReturn 203IOFWUserObjectExporter::addObject ( OSObject * obj, CleanupFunction cleanupFunction, IOFireWireLib::UserObjectHandle * outHandle ) 204{ 205 IOReturn error = kIOReturnSuccess ; 206 207 lock () ; 208 209 if ( ! fObjects ) 210 { 211 fCapacity = 8 ; 212 fObjects = (const OSObject **) new const OSObject * [ fCapacity ] ; 213 fCleanupFunctions = new CleanupFunctionWithExporter[ fCapacity ] ; 214 215 if ( ! fObjects || !fCleanupFunctions ) 216 { 217 DebugLog( "Couldn't make fObjects\n" ) ; 218 error = kIOReturnNoMemory ; 219 } 220 } 221 222 // if at capacity, expand pool 223 if ( fObjectCount == fCapacity ) 224 { 225 unsigned newCapacity = fCapacity + ( fCapacity >> 1 ) ; 226 if ( newCapacity > 0xFFFE ) 227 newCapacity = 0xFFFE ; 228 229 if ( newCapacity == fCapacity ) // can't grow! 230 { 231 DebugLog( "Can't grow object exporter\n" ) ; 232 error = kIOReturnNoMemory ; 233 } 234 235 const OSObject ** newObjects = NULL ; 236 CleanupFunctionWithExporter * newCleanupFunctions = NULL ; 237 238 if ( ! error ) 239 { 240 newObjects = (const OSObject **) new OSObject * [ newCapacity ] ; 241 242 if ( !newObjects ) 243 error = kIOReturnNoMemory ; 244 } 245 246 if ( !error ) 247 { 248 newCleanupFunctions = new CleanupFunctionWithExporter[ newCapacity ] ; 249 if ( !newCleanupFunctions ) 250 error = kIOReturnNoMemory ; 251 } 252 253 if ( ! error ) 254 { 255 bcopy ( fObjects, newObjects, fCapacity * sizeof ( OSObject * ) ) ; 256 delete[] fObjects ; 257 258 bcopy ( fCleanupFunctions, newCleanupFunctions, fCapacity * sizeof( CleanupFunction * ) ) ; 259 delete[] fCleanupFunctions ; 260 261 fObjects = newObjects ; 262 fCleanupFunctions = newCleanupFunctions ; 263 fCapacity = newCapacity ; 264 } 265 } 266 267 if ( ! error ) 268 { 269 error = kIOReturnNoMemory ; 270 unsigned index = 0 ; 271 272 while ( index < fCapacity ) 273 { 274 if ( ! fObjects [ index ] ) 275 { 276 obj->retain () ; 277 fObjects[ index ] = obj ; 278 fCleanupFunctions[ index ] = (CleanupFunctionWithExporter)cleanupFunction ; 279 *outHandle = (IOFireWireLib::UserObjectHandle)(index + 1) ; // return index + 1; this means 0 is always an invalid/NULL index... 280 ++fObjectCount ; 281 error = kIOReturnSuccess ; 282 break ; 283 } 284 285 ++index ; 286 } 287 } 288 289 unlock () ; 290 291 ErrorLogCond( error, "fExporter->addObject returning error %x\n", error ) ; 292 293 return error ; 294} 295 296void 297IOFWUserObjectExporter::removeObject ( IOFireWireLib::UserObjectHandle handle ) 298{ 299 if ( !handle ) 300 { 301 return ; 302 } 303 304 lock () ; 305 306 DebugLog("user object exporter removing handle %d\n", (uint32_t)handle); 307 308 unsigned index = (unsigned)handle - 1 ; // handle is object's index + 1; this means 0 is always in invalid/NULL index... 309 310 const OSObject * object = NULL ; 311 CleanupFunctionWithExporter cleanupFunction = NULL ; 312 313 if ( fObjects && ( index < fCapacity ) ) 314 { 315 if ( fObjects[ index ] ) 316 { 317 DebugLog( "found object %p (%s), retain count=%d\n", fObjects[ index ], fObjects[ index ]->getMetaClass()->getClassName(), fObjects[ index ]->getRetainCount() ); 318 319 object = fObjects[ index ] ; 320 fObjects[ index ] = NULL ; 321 322 cleanupFunction = fCleanupFunctions[ index ] ; 323 fCleanupFunctions[ index ] = NULL ; 324 325 --fObjectCount ; 326 } 327 } 328 329 unlock () ; 330 331 if ( object ) 332 { 333 if ( cleanupFunction ) 334 { 335 InfoLog("IOFWUserObjectExporter<%p>::removeObject() -- calling cleanup function for object %p of class %s\n", this, object, object->getMetaClass()->getClassName() ) ; 336 (*cleanupFunction)( object, this ) ; 337 } 338 339 object->release() ; 340 } 341 342} 343 344const IOFireWireLib::UserObjectHandle 345IOFWUserObjectExporter::lookupHandle ( OSObject * object ) const 346{ 347 IOFireWireLib::UserObjectHandle out_handle = 0; 348 349 if ( !object ) 350 { 351 return NULL; 352 } 353 354 lock () ; 355 356 unsigned index = 0 ; 357 358 while ( index < fCapacity ) 359 { 360 if( fObjects[index] == object ) 361 { 362 out_handle = (IOFireWireLib::UserObjectHandle)(index + 1) ; // return index + 1; this means 0 is always an invalid/NULL index... 363 break; 364 } 365 366 ++index; 367 } 368 369 unlock (); 370 371 return out_handle; 372} 373 374const OSObject * 375IOFWUserObjectExporter::lookupObject ( IOFireWireLib::UserObjectHandle handle ) const 376{ 377 if ( !handle ) 378 { 379 return NULL ; 380 } 381 382 const OSObject * result = NULL ; 383 384 lock () ; 385 386 unsigned index = (unsigned)handle - 1 ; 387 388 if ( fObjects && ( index < fCapacity ) ) 389 { 390 result = fObjects [ index ] ; 391 if ( result ) 392 { 393 result->retain() ; 394 } 395 } 396 397 unlock () ; 398 399 return result ; 400} 401 402const OSObject * 403IOFWUserObjectExporter::lookupObjectForType( IOFireWireLib::UserObjectHandle handle, const OSMetaClass * toType ) const 404{ 405 if( !handle ) 406 { 407 return NULL; 408 } 409 410 const OSObject * result = NULL; 411 412 lock (); 413 414 unsigned index = (unsigned)handle - 1; 415 416 if ( fObjects && ( index < fCapacity ) ) 417 { 418 result = fObjects [ index ]; 419 } 420 421 if( result ) 422 { 423 result = (OSObject*)OSMetaClassBase::safeMetaCast( result, toType ); 424 } 425 426 if( result ) 427 { 428 result->retain(); 429 } 430 431 unlock (); 432 433 return result; 434} 435 436void 437IOFWUserObjectExporter::removeAllObjects () 438{ 439 lock () ; 440 441 const OSObject ** objects = NULL ; 442 CleanupFunctionWithExporter * cleanupFunctions = NULL ; 443 444 unsigned capacity = fCapacity ; 445 446 if ( fObjects ) 447 { 448 objects = (const OSObject **)IOMalloc( sizeof(const OSObject *) * capacity ) ; 449 cleanupFunctions = (CleanupFunctionWithExporter*)IOMalloc( sizeof( CleanupFunctionWithExporter ) * capacity ) ; 450 451 if ( objects ) 452 bcopy( fObjects, objects, sizeof( const OSObject * ) * capacity ) ; 453 454 if ( cleanupFunctions ) 455 bcopy( fCleanupFunctions, cleanupFunctions, sizeof( CleanupFunction) * capacity ) ; 456 457 delete[] fObjects ; 458 fObjects = NULL ; 459 460 delete[] fCleanupFunctions ; 461 fCleanupFunctions = NULL ; 462 463 fObjectCount = 0 ; 464 fCapacity = 0 ; 465 } 466 467 unlock() ; 468 469 if ( objects && cleanupFunctions ) 470 { 471 for ( unsigned index=0; index < capacity; ++index ) 472 { 473 if ( objects[index] ) 474 { 475 InfoLog("IOFWUserObjectExporter<%p>::removeAllObjects() -- remove object %p of class %s\n", this, objects[ index ], objects[ index ]->getMetaClass()->getClassName() ) ; 476 477 if ( cleanupFunctions[ index ] ) 478 { 479 InfoLog("IOFWUserObjectExporter<%p>::removeAllObjects() -- calling cleanup function for object %p of type %s\n", this, objects[ index ], objects[ index ]->getMetaClass()->getClassName() ) ; 480 (*cleanupFunctions[ index ])( objects[ index ], this ) ; 481 } 482 483 objects[index]->release() ; 484 } 485 } 486 487 IOFree( objects, sizeof(const OSObject *) * capacity ) ; 488 IOFree( cleanupFunctions, sizeof( CleanupFunction ) * capacity ) ; 489 } 490} 491 492// getOwner 493// 494// 495 496OSObject * 497IOFWUserObjectExporter::getOwner() const 498{ 499 return fOwner; 500} 501 502// lock 503// 504// 505 506void 507IOFWUserObjectExporter::lock( void ) const 508{ 509 IOLockLock ( fLock ); 510} 511 512// unlock 513// 514// 515 516void 517IOFWUserObjectExporter::unlock( void ) const 518{ 519 IOLockUnlock ( fLock ); 520} 521 522