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 #include "nvreftrack.h" |
| 34 #include "nvos.h" |
| 35 #include "nvassert.h" |
| 36 |
| 37 #define NVRT_MAX_PACKAGES 8 |
| 38 #define NVRT_MAX_OBJ_TYPES_PER_PACKAGE 8 |
| 39 #define NVRT_CLIENT_SIZE_INCR 16 |
| 40 #define NVRT_OBJ_SIZE_INCR 128 |
| 41 |
| 42 typedef struct |
| 43 { |
| 44 // linked list next ptr (live and free objects) |
| 45 NvU32 NextObj; |
| 46 // the opaque ptr identifier of the object |
| 47 void* Ptr; |
| 48 } NvRtObj; |
| 49 |
| 50 typedef struct |
| 51 { |
| 52 union |
| 53 { |
| 54 // linked list next ptr for free list, -1 == none |
| 55 NvU32 NextFree; |
| 56 // in use client refcount, -1 == cleaning up |
| 57 NvS32 RefCount; |
| 58 } State; |
| 59 |
| 60 void* UserData; |
| 61 |
| 62 // lists of objects per obj type. array size can't |
| 63 // be determined compile time so this is not declared |
| 64 //NvU32 Objs[]; |
| 65 } NvRtClient; |
| 66 |
| 67 typedef struct NvRtRec |
| 68 { |
| 69 NvOsMutexHandle Mutex; |
| 70 |
| 71 NvU32 NumPackages; |
| 72 NvU32 MaxTypesPerPkg; |
| 73 NvU32* ObjTypeIdxLUT; |
| 74 NvU32 NumObjTypes; |
| 75 |
| 76 NvU8* ClientArr; |
| 77 NvU32 ClientArrSize; |
| 78 NvU32 FreeClientList; |
| 79 |
| 80 NvRtObj* ObjArr; |
| 81 NvU32 ObjArrSize; |
| 82 NvU32 FreeObjList; |
| 83 } NvRt; |
| 84 |
| 85 static NV_INLINE NvU32 |
| 86 NvRtClientSize(NvRt* Rt) |
| 87 { |
| 88 return sizeof(NvRtClient) + Rt->NumObjTypes*sizeof(NvU32); |
| 89 } |
| 90 |
| 91 static NV_INLINE NvRtClient* |
| 92 GetClient(NvRt* Rt, NvU32 Idx) |
| 93 { |
| 94 void* ptr = (void*)(Rt->ClientArr + Idx*NvRtClientSize(Rt)); |
| 95 return (NvRtClient*)ptr; |
| 96 } |
| 97 |
| 98 static NV_INLINE NvU32 |
| 99 GetObjTypeIdx(NvRt* Rt, NvU32 Package, NvU32 Type) |
| 100 { |
| 101 NvU32 LutIdx = Package*Rt->MaxTypesPerPkg + Type; |
| 102 NvU32 Idx; |
| 103 |
| 104 Idx = Rt->ObjTypeIdxLUT[LutIdx]; |
| 105 NV_ASSERT(Idx != (NvU32)-1); |
| 106 |
| 107 return Idx; |
| 108 } |
| 109 |
| 110 static NV_INLINE NvU32* |
| 111 GetObjListHead(NvRt* Rt, NvU32 ClientIdx, NvU32 ObjIdx) |
| 112 { |
| 113 NvRtClient* Client = GetClient(Rt, ClientIdx); |
| 114 NvU32* Objs = (NvU32*)(Client + 1); |
| 115 return Objs + ObjIdx; |
| 116 } |
| 117 |
| 118 // Temporary wrapper for realloc as the linux kernel nvos doesn't |
| 119 // implement NvOsRealloc |
| 120 static NV_INLINE void* |
| 121 NvRtRealloc(void* old, size_t size, size_t oldsize) |
| 122 { |
| 123 #if NVOS_IS_LINUX_KERNEL |
| 124 void* ret; |
| 125 |
| 126 if (!size) |
| 127 { |
| 128 if (old) NvOsFree(old); |
| 129 return NULL; |
| 130 } |
| 131 |
| 132 ret = NvOsAlloc(size); |
| 133 |
| 134 if (ret && old) |
| 135 { |
| 136 NV_ASSERT(oldsize > 0); |
| 137 |
| 138 NvOsMemcpy(ret, old, NV_MIN(size, oldsize)); |
| 139 NvOsFree(old); |
| 140 } |
| 141 |
| 142 return ret; |
| 143 #else |
| 144 return NvOsRealloc(old, size); |
| 145 #endif |
| 146 } |
| 147 |
| 148 NvError NvRtCreate( |
| 149 NvU32 NumPackages, |
| 150 const NvU32* NumObjTypesPerPackage, |
| 151 NvRtHandle* RtOut) |
| 152 { |
| 153 NvRtHandle Ctx; |
| 154 NvU32 i; |
| 155 |
| 156 if (NumPackages == 0) |
| 157 { |
| 158 NV_ASSERT(!"Zero packages is not allowed"); |
| 159 return NvError_BadParameter; |
| 160 } |
| 161 |
| 162 if (NumPackages > NVRT_MAX_PACKAGES) |
| 163 { |
| 164 NV_ASSERT(!"NumPackages exceeds NVRT_MAX_PACKAGES"); |
| 165 return NvError_BadParameter; |
| 166 } |
| 167 |
| 168 Ctx = NvOsAlloc(sizeof(NvRt)); |
| 169 if (!Ctx) return NvError_InsufficientMemory; |
| 170 NvOsMemset(Ctx, 0, sizeof(NvRt)); |
| 171 |
| 172 Ctx->FreeClientList = -1; |
| 173 Ctx->FreeObjList = -1; |
| 174 Ctx->NumPackages = NumPackages; |
| 175 |
| 176 for (i = 0; i < NumPackages; i++) |
| 177 { |
| 178 if (NumObjTypesPerPackage[i] > |
| 179 NVRT_MAX_OBJ_TYPES_PER_PACKAGE) |
| 180 { |
| 181 NV_ASSERT(!"Too many object types"); |
| 182 NvOsFree(Ctx); |
| 183 return NvError_BadParameter; |
| 184 } |
| 185 |
| 186 Ctx->NumObjTypes += NumObjTypesPerPackage[i]; |
| 187 |
| 188 if (NumObjTypesPerPackage[i] > Ctx->MaxTypesPerPkg) |
| 189 Ctx->MaxTypesPerPkg = NumObjTypesPerPackage[i]; |
| 190 } |
| 191 |
| 192 if (Ctx->MaxTypesPerPkg) |
| 193 { |
| 194 NvU32 idx = 0; |
| 195 |
| 196 Ctx->ObjTypeIdxLUT = NvOsAlloc(sizeof(NvU32)*Ctx->MaxTypesPerPkg*NumPack
ages); |
| 197 if (!Ctx->ObjTypeIdxLUT) |
| 198 { |
| 199 NvOsFree(Ctx); |
| 200 return NvError_InsufficientMemory; |
| 201 } |
| 202 |
| 203 for (i = 0; i < NumPackages; i++) |
| 204 { |
| 205 NvU32 start = i*Ctx->MaxTypesPerPkg; |
| 206 NvU32 j = 0; |
| 207 |
| 208 for (; j < NumObjTypesPerPackage[i]; j++) |
| 209 { |
| 210 Ctx->ObjTypeIdxLUT[start+j] = idx++; |
| 211 } |
| 212 for (; j < Ctx->MaxTypesPerPkg; j++) |
| 213 { |
| 214 Ctx->ObjTypeIdxLUT[start+j] = (NvU32)-1; |
| 215 } |
| 216 } |
| 217 } |
| 218 |
| 219 if (NvOsMutexCreate(&Ctx->Mutex) != NvSuccess) |
| 220 { |
| 221 NvOsFree(Ctx->ObjTypeIdxLUT); |
| 222 NvOsFree(Ctx); |
| 223 return NvError_InsufficientMemory; |
| 224 } |
| 225 |
| 226 *RtOut = Ctx; |
| 227 return NvSuccess; |
| 228 } |
| 229 |
| 230 void NvRtDestroy(NvRtHandle Rt) |
| 231 { |
| 232 NvOsMutexDestroy(Rt->Mutex); |
| 233 NvOsFree(Rt->ObjTypeIdxLUT); |
| 234 NvOsFree(Rt); |
| 235 } |
| 236 |
| 237 NvError NvRtRegisterClient( |
| 238 NvRtHandle Rt, |
| 239 NvRtClientHandle* ClientOut) |
| 240 { |
| 241 NvOsMutexLock(Rt->Mutex); |
| 242 |
| 243 // Allocate new clients if necessary |
| 244 |
| 245 if (Rt->FreeClientList == -1) |
| 246 { |
| 247 NvU8* NewArr; |
| 248 NvU32 NewSize; |
| 249 NvU32 i; |
| 250 |
| 251 // Grow array by increment |
| 252 |
| 253 NewSize = Rt->ClientArrSize + NVRT_CLIENT_SIZE_INCR; |
| 254 NewArr = NvRtRealloc(Rt->ClientArr, |
| 255 NvRtClientSize(Rt)*NewSize, |
| 256 NvRtClientSize(Rt)*Rt->ClientArrSize); |
| 257 if (NewArr == NULL) |
| 258 { |
| 259 NvOsMutexUnlock(Rt->Mutex); |
| 260 return NvError_InsufficientMemory; |
| 261 } |
| 262 Rt->ClientArr = NewArr; |
| 263 |
| 264 // Initialize new clients and create free list |
| 265 |
| 266 for (i = Rt->ClientArrSize; i < NewSize; i++) |
| 267 { |
| 268 NvRtClient* c = GetClient(Rt, i); |
| 269 NvU32* objs = (NvU32*)(c+1); |
| 270 NvU32 j; |
| 271 |
| 272 c->State.NextFree = (i == NewSize-1) ? -1 : i+1; |
| 273 |
| 274 for (j = 0; j < Rt->NumObjTypes; j++) |
| 275 objs[j] = -1; |
| 276 } |
| 277 |
| 278 Rt->FreeClientList = Rt->ClientArrSize; |
| 279 Rt->ClientArrSize = NewSize; |
| 280 } |
| 281 |
| 282 NV_ASSERT(Rt->FreeClientList != -1); |
| 283 |
| 284 { |
| 285 NvU32 ClientIdx = Rt->FreeClientList; |
| 286 NvRtClient* Client = GetClient(Rt, ClientIdx); |
| 287 |
| 288 Rt->FreeClientList = Client->State.NextFree; |
| 289 |
| 290 NvOsMutexUnlock(Rt->Mutex); |
| 291 |
| 292 // Initialize client |
| 293 |
| 294 Client->State.RefCount = 1; |
| 295 Client->UserData = NULL; |
| 296 |
| 297 *ClientOut = ClientIdx + 1; |
| 298 } |
| 299 |
| 300 return NvSuccess; |
| 301 } |
| 302 |
| 303 NvError NvRtAddClientRef( |
| 304 NvRtHandle Rt, |
| 305 NvRtClientHandle ClientHandle) |
| 306 { |
| 307 NvRtClient* Client; |
| 308 NvU32 ClientIdx = ClientHandle - 1; |
| 309 NvError Ret = NvSuccess; |
| 310 |
| 311 NV_ASSERT(ClientHandle != 0); |
| 312 NV_ASSERT(ClientHandle <= Rt->ClientArrSize); |
| 313 |
| 314 NvOsMutexLock(Rt->Mutex); |
| 315 |
| 316 Client = GetClient(Rt, ClientIdx); |
| 317 |
| 318 if (Client->State.RefCount < 1) |
| 319 Ret = NvError_InvalidState; |
| 320 else |
| 321 Client->State.RefCount++; |
| 322 |
| 323 NvOsMutexUnlock(Rt->Mutex); |
| 324 |
| 325 return Ret; |
| 326 } |
| 327 |
| 328 NvBool NvRtUnregisterClient( |
| 329 NvRtHandle Rt, |
| 330 NvRtClientHandle ClientHandle) |
| 331 { |
| 332 NvRtClient* Client; |
| 333 NvU32 ClientIdx = ClientHandle - 1; |
| 334 NvU32* Objs; |
| 335 NvU32 i; |
| 336 |
| 337 NV_ASSERT(ClientHandle != 0); |
| 338 NV_ASSERT(ClientHandle <= Rt->ClientArrSize); |
| 339 |
| 340 NvOsMutexLock(Rt->Mutex); |
| 341 |
| 342 Client = GetClient(Rt, ClientIdx); |
| 343 Client->State.RefCount--; |
| 344 |
| 345 if (Client->State.RefCount >= 0) |
| 346 { |
| 347 NvBool DoClean = (Client->State.RefCount == 0); |
| 348 NvOsMutexUnlock(Rt->Mutex); |
| 349 return DoClean; |
| 350 } |
| 351 |
| 352 Objs = (NvU32*)(Client+1); |
| 353 |
| 354 // Check that object references are free'd |
| 355 |
| 356 for (i = Rt->NumObjTypes; i != 0; i--) |
| 357 { |
| 358 NvU32 Idx = i - 1; |
| 359 NvU32 Cur = Objs[Idx]; |
| 360 |
| 361 // The caller should free all object referenced before |
| 362 // unregistering. Assert that this is so. |
| 363 |
| 364 NV_ASSERT(Cur == -1 || !"Leaked object reference"); |
| 365 |
| 366 // In release builds free at least our state for the leaked |
| 367 // objects. There's nothing we can do about the leaked objects. |
| 368 |
| 369 while (Cur != -1) |
| 370 { |
| 371 NvRtObj* Obj = &Rt->ObjArr[Cur]; |
| 372 NvU32 Next = Obj->NextObj; |
| 373 |
| 374 Obj->NextObj = Rt->FreeObjList; |
| 375 Rt->FreeObjList = Cur; |
| 376 Cur = Next; |
| 377 } |
| 378 |
| 379 Objs[Idx] = -1; |
| 380 } |
| 381 |
| 382 // Release client |
| 383 |
| 384 Client->State.NextFree = Rt->FreeClientList; |
| 385 Rt->FreeClientList = ClientIdx; |
| 386 |
| 387 NvOsMutexUnlock(Rt->Mutex); |
| 388 |
| 389 return NV_FALSE; |
| 390 } |
| 391 |
| 392 void NvRtSetClientUserData( |
| 393 NvRtHandle Rt, |
| 394 NvRtClientHandle ClientHandle, |
| 395 void* UserData) |
| 396 { |
| 397 NvRtClient* Client; |
| 398 NvU32 ClientIdx = ClientHandle - 1; |
| 399 |
| 400 NV_ASSERT(ClientHandle != 0); |
| 401 NV_ASSERT(ClientHandle <= Rt->ClientArrSize); |
| 402 |
| 403 NvOsMutexLock(Rt->Mutex); |
| 404 |
| 405 Client = GetClient(Rt, ClientIdx); |
| 406 Client->UserData = UserData; |
| 407 |
| 408 NvOsMutexUnlock(Rt->Mutex); |
| 409 } |
| 410 |
| 411 void* NvRtGetClientUserData( |
| 412 NvRtHandle Rt, |
| 413 NvRtClientHandle ClientHandle) |
| 414 { |
| 415 NvRtClient* Client; |
| 416 NvU32 ClientIdx = ClientHandle - 1; |
| 417 void* UserData; |
| 418 |
| 419 NV_ASSERT(ClientHandle != 0); |
| 420 NV_ASSERT(ClientHandle <= Rt->ClientArrSize); |
| 421 |
| 422 NvOsMutexLock(Rt->Mutex); |
| 423 |
| 424 Client = GetClient(Rt, ClientIdx); |
| 425 UserData = Client->UserData; |
| 426 |
| 427 NvOsMutexUnlock(Rt->Mutex); |
| 428 |
| 429 return UserData; |
| 430 } |
| 431 |
| 432 NvError NvRtAllocObjRef( |
| 433 const NvDispatchCtx* Ctx, |
| 434 NvRtObjRefHandle* Out) |
| 435 { |
| 436 NvRt* Rt = Ctx->Rt; |
| 437 NvU32 ObjIdx; |
| 438 NvRtObj* Obj; |
| 439 |
| 440 NvOsMutexLock(Rt->Mutex); |
| 441 |
| 442 // Allocate new space if necessary |
| 443 |
| 444 if (Rt->FreeObjList == -1) |
| 445 { |
| 446 NvRtObj* NewArr; |
| 447 NvRtObj* Cur; |
| 448 NvU32 NewSize; |
| 449 NvU32 i; |
| 450 |
| 451 // Grow array by increment |
| 452 |
| 453 NewSize = Rt->ObjArrSize + NVRT_OBJ_SIZE_INCR; |
| 454 NewArr = NvRtRealloc(Rt->ObjArr, |
| 455 sizeof(NvRtObj)*NewSize, |
| 456 sizeof(NvRtObj)*Rt->ObjArrSize); |
| 457 if (NewArr == NULL) |
| 458 { |
| 459 NvOsMutexUnlock(Rt->Mutex); |
| 460 return NvError_InsufficientMemory; |
| 461 } |
| 462 |
| 463 // Create free list |
| 464 |
| 465 Cur = NewArr + Rt->ObjArrSize; |
| 466 for (i = Rt->ObjArrSize + 1; i < NewSize; i++) |
| 467 { |
| 468 Cur->NextObj = i; |
| 469 Cur++; |
| 470 } |
| 471 Cur->NextObj = -1; |
| 472 |
| 473 // Store new values |
| 474 |
| 475 Rt->ObjArr = NewArr; |
| 476 Rt->FreeObjList = Rt->ObjArrSize; |
| 477 Rt->ObjArrSize = NewSize; |
| 478 } |
| 479 |
| 480 NV_ASSERT(Rt->FreeObjList != -1); |
| 481 |
| 482 ObjIdx = Rt->FreeObjList; |
| 483 Obj = &Rt->ObjArr[ObjIdx]; |
| 484 Rt->FreeObjList = Obj->NextObj; |
| 485 |
| 486 Obj->NextObj = -1; |
| 487 Obj->Ptr = NULL; |
| 488 |
| 489 NvOsMutexUnlock(Rt->Mutex); |
| 490 |
| 491 *Out = ObjIdx + 1; |
| 492 return NvSuccess; |
| 493 } |
| 494 |
| 495 void NvRtDiscardObjRef( |
| 496 const NvDispatchCtx* Ctx, |
| 497 NvRtObjRefHandle ObjRef) |
| 498 { |
| 499 NvRt* Rt = Ctx->Rt; |
| 500 NvRtObj* Obj; |
| 501 |
| 502 if (!ObjRef--) return; |
| 503 |
| 504 NvOsMutexLock(Rt->Mutex); |
| 505 |
| 506 Obj = &Rt->ObjArr[ObjRef]; |
| 507 |
| 508 NV_ASSERT(Obj->NextObj == -1); |
| 509 NV_ASSERT(Obj->Ptr == NULL); |
| 510 |
| 511 Obj->NextObj = Rt->FreeObjList; |
| 512 Rt->FreeObjList = ObjRef; |
| 513 |
| 514 NvOsMutexUnlock(Rt->Mutex); |
| 515 } |
| 516 |
| 517 void NvRtStoreObjRef( |
| 518 const NvDispatchCtx* Ctx, |
| 519 NvRtObjRefHandle ObjRef, |
| 520 NvU32 ObjType, |
| 521 void* ObjPtr) |
| 522 { |
| 523 NvRt* Rt = Ctx->Rt; |
| 524 NvU32 ClientIdx = Ctx->Client - 1; |
| 525 NvU32 ObjTypeIdx = GetObjTypeIdx(Rt, Ctx->PackageIdx, ObjType); |
| 526 NvRtObj* Obj; |
| 527 NvU32* List; |
| 528 |
| 529 NV_ASSERT(ClientIdx < Rt->ClientArrSize); |
| 530 |
| 531 if (ObjPtr == NULL) |
| 532 { |
| 533 NV_ASSERT(!"Bad object ptr"); |
| 534 return; |
| 535 } |
| 536 |
| 537 if (!ObjRef--) |
| 538 { |
| 539 NV_ASSERT(!"Bad object ref handle"); |
| 540 return; |
| 541 } |
| 542 |
| 543 NvOsMutexLock(Rt->Mutex); |
| 544 |
| 545 Obj = &Rt->ObjArr[ObjRef]; |
| 546 |
| 547 NV_ASSERT(Obj->NextObj == -1); |
| 548 NV_ASSERT(Obj->Ptr == NULL); |
| 549 |
| 550 List = GetObjListHead(Rt, ClientIdx, ObjTypeIdx); |
| 551 |
| 552 Obj->NextObj = *List; |
| 553 Obj->Ptr = ObjPtr; |
| 554 |
| 555 *List = ObjRef; |
| 556 |
| 557 NvOsMutexUnlock(Rt->Mutex); |
| 558 } |
| 559 |
| 560 void* NvRtFreeObjRef( |
| 561 const NvDispatchCtx* Ctx, |
| 562 NvU32 ObjType, |
| 563 void* ObjPtr) |
| 564 { |
| 565 NvRt* Rt = Ctx->Rt; |
| 566 NvU32 ClientIdx = Ctx->Client - 1; |
| 567 NvU32 ObjTypeIdx = GetObjTypeIdx(Rt, Ctx->PackageIdx, ObjType); |
| 568 NvU32 PrevIdx; |
| 569 NvU32 CurIdx; |
| 570 NvU32* List; |
| 571 void* RetVal = NULL; |
| 572 |
| 573 NV_ASSERT(ClientIdx < Rt->ClientArrSize); |
| 574 |
| 575 NvOsMutexLock(Rt->Mutex); |
| 576 |
| 577 List = GetObjListHead(Rt, ClientIdx, ObjTypeIdx); |
| 578 CurIdx = *List; |
| 579 PrevIdx = -1; |
| 580 |
| 581 // If user requested to find a specific object look it up |
| 582 |
| 583 if (ObjPtr != NULL) |
| 584 { |
| 585 while (CurIdx != -1) |
| 586 { |
| 587 NvRtObj* Obj = &Rt->ObjArr[CurIdx]; |
| 588 |
| 589 if (Obj->Ptr == ObjPtr) break; |
| 590 |
| 591 PrevIdx = CurIdx; |
| 592 CurIdx = Obj->NextObj; |
| 593 } |
| 594 |
| 595 // User should not ask to free non-existent objects |
| 596 |
| 597 if (CurIdx == -1) |
| 598 { |
| 599 NV_ASSERT(!"Trying to free non-existent object reference"); |
| 600 NvOsMutexUnlock(Rt->Mutex); |
| 601 return NULL; |
| 602 } |
| 603 } |
| 604 |
| 605 // If we have an object, free it |
| 606 |
| 607 if (CurIdx != -1) |
| 608 { |
| 609 NvRtObj* Obj = &Rt->ObjArr[CurIdx]; |
| 610 |
| 611 RetVal = Obj->Ptr; |
| 612 |
| 613 if (PrevIdx == -1) |
| 614 { |
| 615 *List = Obj->NextObj; |
| 616 } |
| 617 else |
| 618 { |
| 619 NvRtObj* PrevObj = &Rt->ObjArr[PrevIdx]; |
| 620 PrevObj->NextObj = Obj->NextObj; |
| 621 } |
| 622 |
| 623 Obj->Ptr = NULL; |
| 624 Obj->NextObj = Rt->FreeObjList; |
| 625 Rt->FreeObjList = CurIdx; |
| 626 } |
| 627 |
| 628 NvOsMutexUnlock(Rt->Mutex); |
| 629 |
| 630 return RetVal; |
| 631 } |
| 632 |
| 633 #include <linux/module.h> |
| 634 |
| 635 EXPORT_SYMBOL(NvRtAllocObjRef); |
| 636 EXPORT_SYMBOL(NvRtDiscardObjRef); |
| 637 EXPORT_SYMBOL(NvRtFreeObjRef); |
| 638 EXPORT_SYMBOL(NvRtStoreObjRef); |
| 639 |
| 640 EXPORT_SYMBOL(NvRtCreate); |
| 641 EXPORT_SYMBOL(NvRtDestroy); |
| 642 EXPORT_SYMBOL(NvRtRegisterClient); |
| 643 EXPORT_SYMBOL(NvRtUnregisterClient); |
OLD | NEW |