OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2009 NVIDIA Corporation. |
| 3 * All rights reserved. |
| 4 * |
| 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: |
| 7 * |
| 8 * Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. |
| 10 * |
| 11 * Redistributions in binary form must reproduce the above copyright notice, |
| 12 * this list of conditions and the following disclaimer in the documentation |
| 13 * and/or other materials provided with the distribution. |
| 14 * |
| 15 * Neither the name of the NVIDIA Corporation nor the names of its contributors |
| 16 * may be used to endorse or promote products derived from this software |
| 17 * without specific prior written permission. |
| 18 * |
| 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 * POSSIBILITY OF SUCH DAMAGE. |
| 30 * |
| 31 */ |
| 32 |
| 33 /** |
| 34 * \file nvreftrack.h |
| 35 * \brief NVIDIA kernel object reference tracking utility |
| 36 * |
| 37 * \mainpage |
| 38 * |
| 39 * NvRefTrack implements a database of client to object |
| 40 * references. The sole purpose of the utility is to provide a |
| 41 * mechanism for freeing up kernel mode driver objects on abnormal |
| 42 * client termination. |
| 43 * |
| 44 * This utility is intended to be used together with the NV IDL |
| 45 * automatic call dispatcher generation. 'refadd' and 'refdel' |
| 46 * modifiers for function parameters instruct the IDL generation to |
| 47 * instrument the dispatcher functions with appropriate calls to |
| 48 * NvRtStoreObjRef() and NvRtFreeObjRef(). |
| 49 * |
| 50 * The OS specific kernel driver's responsibility is to create the |
| 51 * NvRt context and to register and unregister clients (user mode |
| 52 * processes accessing the driver). Additionally the context and the |
| 53 * calling client handle need to be passed to the master dispatcher. |
| 54 */ |
| 55 |
| 56 #ifndef INCLUDED_NVREFTRACK_H |
| 57 #define INCLUDED_NVREFTRACK_H |
| 58 |
| 59 #include "nvcommon.h" |
| 60 #include "nverror.h" |
| 61 |
| 62 #ifndef NVRT_ENABLE_LEAK_PRINT |
| 63 #define NVRT_ENABLE_LEAK_PRINT NV_DEBUG |
| 64 #endif |
| 65 |
| 66 /*---------------------------------------------------------*/ |
| 67 /** \defgroup objtype Tracked object types |
| 68 * |
| 69 * NvRefTrack must be able to identify the object types |
| 70 * stored in the database. As the IDL generator can not |
| 71 * produce a list of the types they are statically defined |
| 72 * here. Note that this list of enumerations is not actually |
| 73 * a part of the NvRefTrack public interface - it could be |
| 74 * stored separately. Ideally these enumerations would be |
| 75 * generated by the IDL dispatcher generator. |
| 76 * |
| 77 * The exact syntax of these enumerations is important, as |
| 78 * the IDL generator will refer to these names when creating |
| 79 * reference add/del code in the dispatcher. |
| 80 * |
| 81 * 1) There must a an enumeration for every package that |
| 82 * contains objects to be tracked. The enumeration should |
| 83 * be called NvRtObjType_<package>. |
| 84 * 2) For every object type tracked in the package (every |
| 85 * object type that may have refadd and refdel modifiers |
| 86 * in the idl description) there needs to be an entry in |
| 87 * the enumeration called NvRtObjType_<package>_<type>. |
| 88 * 3) The enumerations should start from value 0 and fill |
| 89 * the number space completely up to |
| 90 * NvRtObjType_<package>_Num, which will be equal to the |
| 91 * number of tracked object types in the package. |
| 92 */ |
| 93 |
| 94 /** |
| 95 * Tracked object types for package NvRm |
| 96 * \ingroup objtype |
| 97 */ |
| 98 typedef enum |
| 99 { |
| 100 NvRtObjType_NvRm_NvRmMemHandle = 0, |
| 101 NvRtObjType_NvRm_Num, |
| 102 NvRtObjType_NvRm_ForceWord = 0x7FFFFFFF |
| 103 } NvRtObjType_NvRm; |
| 104 |
| 105 /** |
| 106 * Tracked handles for package NvRmGraphics |
| 107 * \ingroup objtype |
| 108 */ |
| 109 typedef enum |
| 110 { |
| 111 NvRtObjType_NvRmGraphics_NvRmChannelHandle = 0, |
| 112 NvRtObjType_NvRmGraphics_NvRmContextHandle, |
| 113 NvRtObjType_NvRmGraphics_Num, |
| 114 NvRtObjType_NvRmGraphics_ForceWord = 0x7FFFFFFF |
| 115 } NvRtObjType_NvRmGraphics; |
| 116 |
| 117 /** |
| 118 * Tracked handles for package NvMM |
| 119 * |
| 120 * Tentative handles to track: |
| 121 * - NvMMManagerHandle, this does not exist - API failure? |
| 122 * - NvMMIRAMScratchHandle, this does not exist - API failure? |
| 123 * Can possibly use references to CodecType, a bit dodgy |
| 124 * - pBlock, why is this not a handle? |
| 125 * - pClientId, why is this not a handle? |
| 126 * \ingroup objtype |
| 127 */ |
| 128 typedef enum |
| 129 { |
| 130 NvRtObjType_NvMM_NvmmPowerClientHandle = 0, |
| 131 NvRtObjType_NvMM_NvmmManagerHandle, |
| 132 NvRtObjType_NvMM_NvmmMgrBlockHandle, |
| 133 NvRtObjType_NvMM_Num, |
| 134 NvRtObjType_NvMM_ForceWord = 0x7FFFFFFF |
| 135 } NvRtObjType_NvMM; |
| 136 |
| 137 /** |
| 138 * Tracked handles for package NvECPackage |
| 139 * |
| 140 * Tentative handles to track: |
| 141 * - NvEcHandle |
| 142 * - NvEcEventRegistrationHandle |
| 143 * \ingroup objtype |
| 144 */ |
| 145 typedef enum |
| 146 { |
| 147 NvRtObjType_NvECPackage_NvEcHandle = 0, |
| 148 NvRtObjType_NvECPackage_NvEcEventRegistrationHandle, |
| 149 NvRtObjType_NvECPackage_Num, |
| 150 NvRtObjType_NvECPackage_ForceWord = 0x7FFFFFFF |
| 151 } NvRtObjType_NvECPackage; |
| 152 |
| 153 /** |
| 154 * Tracked handles for package NvStorManager |
| 155 * |
| 156 * Tentative handles to track: |
| 157 * - NvStorMgrFileHandle |
| 158 * \ingroup objtype |
| 159 */ |
| 160 typedef enum |
| 161 { |
| 162 NvRtObjType_NvStorManager_NvStorMgrFileHandle = 0, |
| 163 NvRtObjType_NvStorManager_Num, |
| 164 NvRtObjType_NvStorManager_ForceWord = 0x7FFFFFFF |
| 165 } NvRtObjType_NvStorManager; |
| 166 |
| 167 /** |
| 168 * Tracked handles for package NvDDKAudio |
| 169 * \ingroup objtype |
| 170 */ |
| 171 typedef enum |
| 172 { |
| 173 NvRtObjType_NvDDKAudio_Num = 0, |
| 174 NvRtObjType_NvDDKAudio_ForceWord = 0x7FFFFFFF |
| 175 } NvRtObjType_NvDDKAudio; |
| 176 |
| 177 /** |
| 178 * Tracked handles for package NvDispMgr |
| 179 * \ingroup objtype |
| 180 */ |
| 181 typedef enum |
| 182 { |
| 183 NvRtObjType_NvDispMgr_Client = 0, |
| 184 NvRtObjType_NvDispMgr_Num, |
| 185 NvRtObjType_NvDispMgr_ForceWord = 0x7FFFFFFF |
| 186 } NvRtObjType_NvDispMgr; |
| 187 |
| 188 |
| 189 /*---------------------------------------------------------*/ |
| 190 /** \defgroup os_driver Public interface for os driver */ |
| 191 |
| 192 #if NVRT_ENABLE_LEAK_PRINT |
| 193 #define NVRT_LEAK(driver, objtype, ptr) \ |
| 194 NvOsDebugPrintf("[%s] Leaked reference on client exit: (%s) 0x%08x\n", \ |
| 195 driver, objtype, ptr); |
| 196 #else |
| 197 #define NVRT_LEAK(driver, objtype, ptr) |
| 198 #endif |
| 199 |
| 200 |
| 201 typedef struct NvRtRec* NvRtHandle; |
| 202 typedef NvU32 NvRtClientHandle; |
| 203 typedef NvU32 NvRtObjRefHandle; |
| 204 |
| 205 typedef struct |
| 206 { |
| 207 NvRtHandle Rt; |
| 208 NvRtClientHandle Client; |
| 209 NvU32 PackageIdx; |
| 210 } NvDispatchCtx; |
| 211 |
| 212 |
| 213 #if defined(__cplusplus) |
| 214 extern "C" |
| 215 { |
| 216 #endif |
| 217 |
| 218 /** |
| 219 * Create a reference tracking database. |
| 220 * |
| 221 * The OS driver should create a single database upon driver init for |
| 222 * all the IDL packages that the driver is responsible for. The |
| 223 * created handle should be stored in the global driver context. |
| 224 * |
| 225 * @param NumPackages Number of IDL packages that the driver is |
| 226 * responsible for. |
| 227 * @param NumObjTypesPerPackage A list of the amount of tracked handles |
| 228 * for each of the IDL packages. The order |
| 229 * of the list needs to match the package |
| 230 * indices passed in to the reference |
| 231 * manipulation functions. The XXX_Num value |
| 232 * of the object type enumerations can be used |
| 233 * in constructing the list. |
| 234 * @param RtOut A newly created reference database handle. |
| 235 * @return NvSuccess on success. |
| 236 * |
| 237 * \ingroup os_driver |
| 238 */ |
| 239 NvError NvRtCreate( |
| 240 NvU32 NumPackages, |
| 241 const NvU32* NumObjTypesPerPackage, |
| 242 NvRtHandle* RtOut); |
| 243 |
| 244 /** |
| 245 * Destroy a reference tracking database. |
| 246 * |
| 247 * This frees all resources associated to a reference database and should |
| 248 * be called on driver deinitialization. Note that this function makes no |
| 249 * attempt at freeing any outstanding references, the user must make sure |
| 250 * that references to driver objects have been freed prior to destroying |
| 251 * the database. |
| 252 * |
| 253 * @param Rt The reference database handle. |
| 254 * |
| 255 * \ingroup os_driver |
| 256 */ |
| 257 void NvRtDestroy( |
| 258 NvRtHandle Rt); |
| 259 |
| 260 /** |
| 261 * Register a new client to the reference database. |
| 262 * |
| 263 * For all practical purposes, a client refers to a single entity in the |
| 264 * system that uses the driver via the IDL interface and may terminate |
| 265 * unexpectedly, without freeing the driver resource references it holds. |
| 266 * It makes no sense, for example, to register potential kernel-side users |
| 267 * of the driver into the database as it should be impossible to terminate |
| 268 * such a client unexpectedly without resulting in a complete system failure. |
| 269 * Most commonly, but not necessarily, client == usermode process. |
| 270 * |
| 271 * The client ID returned by this function in the location pointed to by the |
| 272 * ClientOut parameter must be stored in a way that it can be passed along |
| 273 * to the master dispatcher function (in the NvDispatchCtx struct) for all |
| 274 * calls originating from the client. This may, for example, be the return |
| 275 * value from a file handle open (XXX_Open) operation passed back as the |
| 276 * "open context" parameter into XXX_Ioctl calls. |
| 277 * |
| 278 * @param Rt The reference database handle. |
| 279 * @param ClientOut A unique ID for the newly registered client. This |
| 280 * value never equals 0 on success. |
| 281 * @return NvSuccess on success. |
| 282 * |
| 283 * \ingroup os_driver |
| 284 */ |
| 285 NvError NvRtRegisterClient( |
| 286 NvRtHandle Rt, |
| 287 NvRtClientHandle* ClientOut); |
| 288 |
| 289 /** |
| 290 * Add a reference to the already registered client. |
| 291 * |
| 292 * Multiple references to a client may be needed when a single client |
| 293 * can be accessed from multiple entities (processes). |
| 294 * |
| 295 * @param Rt The reference database handle. |
| 296 * @param Client The unique ID of the client. |
| 297 * @return NvSuccess on success. |
| 298 * |
| 299 * \ingroup os_driver |
| 300 */ |
| 301 NvError NvRtAddClientRef( |
| 302 NvRtHandle Rt, |
| 303 NvRtClientHandle Client); |
| 304 |
| 305 /** |
| 306 * Unregister a client from the reference database. |
| 307 * |
| 308 * As client handles are refcounted the caller and nvreftrack must |
| 309 * conspire to know when to process possibly leaked resources. The library |
| 310 * signals the caller about the correct time to free leaked resources by |
| 311 * returning NV_TRUE (standing for: yes, please do cleanup now). |
| 312 * |
| 313 * Upon a return value of NV_TRUE, it is the responsibility of the OS driver to |
| 314 * iterate over the possibly remaining references and implement the tearing |
| 315 * down of those references appropriately. This is accomplished by calling |
| 316 * NvRtFreeObjRef() until no further object pointers are returned by it for |
| 317 * the given (client, package, objtype). After doing the cleanup, the caller |
| 318 * should call NvRtUnregisterClient() once more to actually free the client |
| 319 * handle. |
| 320 * |
| 321 * @param Rt The reference database handle. |
| 322 * @param Client The unique ID of the Client. |
| 323 * @return NV_TRUE if the caller should clean up leaked objects |
| 324 * and call NvRtUnregisterClient() again, NV_FALSE |
| 325 * otherwise. |
| 326 * |
| 327 * \ingroup os_driver |
| 328 */ |
| 329 NvBool NvRtUnregisterClient( |
| 330 NvRtHandle Rt, |
| 331 NvRtClientHandle Client); |
| 332 |
| 333 /** |
| 334 * Set/Get opaque user data associated to a client |
| 335 * |
| 336 * \ingroup os_driver |
| 337 */ |
| 338 |
| 339 void NvRtSetClientUserData( |
| 340 NvRtHandle Rt, |
| 341 NvRtClientHandle Client, |
| 342 void* UserData); |
| 343 void* NvRtGetClientUserData( |
| 344 NvRtHandle Rt, |
| 345 NvRtClientHandle Client); |
| 346 |
| 347 /*---------------------------------------------------------*/ |
| 348 /** \defgroup idl_iface Interface used by generated IDL code |
| 349 * |
| 350 * These functions are mainly intended to be called from the |
| 351 * generated IDL dispatcher code. It is of course possible |
| 352 * to use this interface directly from handwritten driver |
| 353 * code as well. |
| 354 * |
| 355 * An exception to this rule is the NvRtFreeObjRef(), which |
| 356 * the os driver uses to iterate over remaining object |
| 357 * references of a client to be unregistered. |
| 358 **/ |
| 359 |
| 360 /** |
| 361 * Allocate an object reference handle. |
| 362 * |
| 363 * Adding an object reference is broken into two parts, |
| 364 * NvRtAllocObjRef() and NvRtStoreObjRef(). This is so that all |
| 365 * resource allocations for the object reference can be done in |
| 366 * advance to eliminate the need to be able to rollback a driver |
| 367 * object reference add in the generated IDL code. |
| 368 * |
| 369 * The caller must call one of NvRtDiscardObjRef() or |
| 370 * NvRtStoreObjRef() for a NvRtObjRefHandle returned by this |
| 371 * function. Failure to do so will unrecoverably leak the object |
| 372 * reference handle. |
| 373 * |
| 374 * @param Ctx The dispatcher context, filled by the OS driver |
| 375 * @param ObjRef A new handle to an object reference |
| 376 * |
| 377 * \ingroup idl_iface |
| 378 */ |
| 379 NvError NvRtAllocObjRef( |
| 380 const NvDispatchCtx* Ctx, |
| 381 NvRtObjRefHandle* ObjRef); |
| 382 |
| 383 |
| 384 /** |
| 385 * Discard an object reference handle. |
| 386 * |
| 387 * Frees a previously allocated object reference handle without storing |
| 388 * anything in the database. |
| 389 * |
| 390 * @param Ctx The dispatcher context, filled by the OS driver |
| 391 * @param ObjRef An object reference handle |
| 392 * |
| 393 * \ingroup idl_iface |
| 394 */ |
| 395 void NvRtDiscardObjRef( |
| 396 const NvDispatchCtx* Ctx, |
| 397 NvRtObjRefHandle ObjRef); |
| 398 |
| 399 /** |
| 400 * Store an object reference to the database. |
| 401 * |
| 402 * This function adds an object reference to the database. An object |
| 403 * is identified via the the attributes (Ctx.PackageIdx, ObjType, |
| 404 * ObjPtr). The reference is created from Ctx.Client. It is |
| 405 * completely valid to have multiple references to a given object from |
| 406 * the same client, or from multiple clients. |
| 407 * |
| 408 * After calling this function the NvRtObjRefHandle acquired by a call |
| 409 * to NvRtAllocObjRef becomes invalid and may no longer be used for |
| 410 * any other purpose. |
| 411 * |
| 412 * It is the caller's responsibility to make sure that the object type |
| 413 * is within range of the allocated object types for the package. In |
| 414 * practice if the NvRtObjType enumeration is well defined and the |
| 415 * NvRt database correctly initialized with the maximum amount of |
| 416 * objects for the package this should not be an issue. |
| 417 * |
| 418 * @param Ctx The dispatcher context, filled by the OS driver |
| 419 * @param ObjRef An object reference handle |
| 420 * @param ObjType The NvRtObjType of the object to be stored |
| 421 * @param ObjPtr A opaque pointer uniquely identifying the object |
| 422 * that this reference points to. NULL is not allowed. |
| 423 * |
| 424 * \ingroup idl_iface |
| 425 */ |
| 426 void NvRtStoreObjRef( |
| 427 const NvDispatchCtx* Ctx, |
| 428 NvRtObjRefHandle ObjRef, |
| 429 NvU32 ObjType, |
| 430 void* ObjPtr); |
| 431 |
| 432 /** |
| 433 * Find and free an object reference. |
| 434 * |
| 435 * The NvRt API provides no way of enumerating or querying the object |
| 436 * database without simultaneously freeing the object reference as |
| 437 * well. This is intentional - the utility is built for a very |
| 438 * specific purpose and optimized to do that in a fast and robust way. |
| 439 * |
| 440 * This function is used to free a previously stored object |
| 441 * reference. Upon locating an object reference from Ctx.Client to |
| 442 * (Ctx.PackageIdx, ObjType, ObjPtr) it immediately frees the object |
| 443 * reference from the database. |
| 444 * |
| 445 * Passing in NULL as ObjPtr means 'match any', the function will locate and |
| 446 * free the first object reference from Ctx.Client to (Ctx.PackageIdx, |
| 447 * ObjType). This can be used to free all outstanding references from a client, |
| 448 * iterate over all packages and object types that the client may have used, |
| 449 * call NvRtFreeObjRef() with a NULL ObjPtr parameter and free the returned |
| 450 * ObjPtr reference until no more references are returned. |
| 451 * |
| 452 * In any case, if an object reference was found and freed the ObjPtr |
| 453 * of the reference is returned. A NULL return value means that no reference |
| 454 * matching the criteria was found. Note that if the generated IDL code works |
| 455 * correctly this function should never get called with a ObjPtr parameter that |
| 456 * can't be found from the database. |
| 457 * |
| 458 * @param Ctx The dispatcher context, filled by the OS driver |
| 459 * @param ObjType The NvRtObjType of the object to be found |
| 460 * @param ObjPtr A opaque pointer of the object to be found |
| 461 * @return The ObjPtr of the reference free'd, NULL if not found |
| 462 * |
| 463 * \ingroup idl_iface |
| 464 */ |
| 465 void* NvRtFreeObjRef( |
| 466 const NvDispatchCtx* Ctx, |
| 467 NvU32 ObjType, |
| 468 void* ObjPtr); |
| 469 |
| 470 #if defined(__cplusplus) |
| 471 } |
| 472 #endif |
| 473 |
| 474 #endif |
OLD | NEW |