Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1017 lines
25 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. Resource.c
  5. Abstract:
  6. This module implements the executive functions to acquire and release
  7. a shared resource.
  8. Author:
  9. Mark Lucovsky (markl) 04-Aug-1989
  10. Environment:
  11. These routines are statically linked in the caller's executable and
  12. are callable in only from user mode. They make use of Nt system
  13. services.
  14. Revision History:
  15. --*/
  16. #include "precomp.hxx"
  17. #include "dbgutil.h"
  18. #include <tsres.hxx>
  19. #include <isplat.h>
  20. //
  21. // The semaphore wait time before retrying the wait
  22. //
  23. #define INET_RES_TIMEOUT (2 * 60 * 1000)
  24. #define TIMEOUT_BREAK_COUNT 15
  25. #if DBG
  26. LONG g_InetResourcesCreated = 0;
  27. LONG g_InetResourcesDeleted = 0;
  28. #endif
  29. BOOL
  30. InetInitializeResource(
  31. IN PRTL_RESOURCE Resource
  32. )
  33. /*++
  34. Routine Description:
  35. This routine initializes the input resource variable
  36. Arguments:
  37. Resource - Supplies the resource variable being initialized
  38. Return Value:
  39. None
  40. --*/
  41. {
  42. PLATFORM_TYPE platformType;
  43. //
  44. // Initialize the lock fields, the count indicates how many are waiting
  45. // to enter or are in the critical section, LockSemaphore is the object
  46. // to wait on when entering the critical section. SpinLock is used
  47. // for the add interlock instruction.
  48. //
  49. INITIALIZE_CRITICAL_SECTION( &Resource->CriticalSection );
  50. //
  51. // The critical section's DebugInfo field is only valid under NT.
  52. // If we're running under NT, then set the critical section type
  53. // to mark this as a resource. This is useful when debugging resource
  54. // leaks.
  55. //
  56. platformType = IISGetPlatformType();
  57. if( platformType == PtNtServer ||
  58. platformType == PtNtWorkstation ) {
  59. Resource->CriticalSection.DebugInfo->Type = RTL_RESOURCE_TYPE;
  60. }
  61. Resource->DebugInfo = NULL;
  62. //
  63. // Initialize flags so there is a default value.
  64. // (Some apps may set RTL_RESOURCE_FLAGS_LONG_TERM to affect timeouts.)
  65. //
  66. Resource->Flags = 0;
  67. //
  68. // Initialize the shared and exclusive waiting counters and semaphore.
  69. // The counters indicate how many are waiting for access to the resource
  70. // and the semaphores are used to wait on the resource. Note that
  71. // the semaphores can also indicate the number waiting for a resource
  72. // however there is a race condition in the alogrithm on the acquire
  73. // side if count if not updated before the critical section is exited.
  74. //
  75. Resource->SharedSemaphore = IIS_CREATE_SEMAPHORE(
  76. "RTL_RESOURCE::SharedSemaphore",
  77. Resource,
  78. 0,
  79. MAXLONG
  80. );
  81. if ( !Resource->SharedSemaphore ) {
  82. return FALSE;
  83. }
  84. Resource->NumberOfWaitingShared = 0;
  85. Resource->ExclusiveSemaphore = IIS_CREATE_SEMAPHORE(
  86. "RTL_RESOURCE::ExclusiveSemaphore",
  87. Resource,
  88. 0,
  89. MAXLONG
  90. );
  91. if ( !Resource->ExclusiveSemaphore ){
  92. CloseHandle( Resource->SharedSemaphore );
  93. return FALSE;
  94. }
  95. Resource->NumberOfWaitingExclusive = 0;
  96. //
  97. // Initialize the current state of the resource
  98. //
  99. Resource->NumberOfActive = 0;
  100. Resource->ExclusiveOwnerThread = NULL;
  101. #if DBG
  102. InterlockedIncrement( &g_InetResourcesCreated );
  103. #endif
  104. return TRUE;
  105. }
  106. BOOL
  107. InetAcquireResourceShared(
  108. IN PRTL_RESOURCE Resource,
  109. IN BOOL Wait
  110. )
  111. /*++
  112. Routine Description:
  113. The routine acquires the resource for shared access. Upon return from
  114. the procedure the resource is acquired for shared access.
  115. Arguments:
  116. Resource - Supplies the resource to acquire
  117. Wait - Indicates if the call is allowed to wait for the resource
  118. to become available for must return immediately
  119. Return Value:
  120. BOOL - TRUE if the resource is acquired and FALSE otherwise
  121. --*/
  122. {
  123. DWORD ret;
  124. ULONG TimeoutCount = 0;
  125. DWORD TimeoutTime = INET_RES_TIMEOUT;
  126. //
  127. // Enter the critical section
  128. //
  129. EnterCriticalSection(&Resource->CriticalSection);
  130. //
  131. // If it is not currently acquired for exclusive use then we can acquire
  132. // the resource for shared access. Note that this can potentially
  133. // starve an exclusive waiter however, this is necessary given the
  134. // ability to recursively acquire the resource shared. Otherwise we
  135. // might/will reach a deadlock situation where a thread tries to acquire
  136. // the resource recusively shared but is blocked by an exclusive waiter.
  137. //
  138. // The test to reanable not starving an exclusive waiter is:
  139. //
  140. // if ((Resource->NumberOfWaitingExclusive == 0) &&
  141. // (Resource->NumberOfActive >= 0)) {
  142. //
  143. if (Resource->NumberOfActive >= 0) {
  144. //
  145. // The resource is ours, so indicate that we have it and
  146. // exit the critical section
  147. //
  148. Resource->NumberOfActive += 1;
  149. LeaveCriticalSection(&Resource->CriticalSection);
  150. //
  151. // Otherwise check to see if this thread is the one currently holding
  152. // exclusive access to the resource. And if it is then we change
  153. // this shared request to an exclusive recusive request and grant
  154. // access to the resource.
  155. //
  156. } else if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) {
  157. //
  158. // The resource is ours (recusively) so indicate that we have it
  159. // and exit the critial section
  160. //
  161. Resource->NumberOfActive -= 1;
  162. LeaveCriticalSection(&Resource->CriticalSection);
  163. //
  164. // Otherwise we'll have to wait for access.
  165. //
  166. } else {
  167. //
  168. // Check if we are allowed to wait or must return immedately, and
  169. // indicate that we didn't acquire the resource
  170. //
  171. if (!Wait) {
  172. LeaveCriticalSection(&Resource->CriticalSection);
  173. return FALSE;
  174. }
  175. //
  176. // Otherwise we need to wait to acquire the resource.
  177. // To wait we will increment the number of waiting shared,
  178. // release the lock, and wait on the shared semaphore
  179. //
  180. Resource->NumberOfWaitingShared += 1;
  181. LeaveCriticalSection(&Resource->CriticalSection);
  182. rewait:
  183. if ( Resource->Flags & RTL_RESOURCE_FLAG_LONG_TERM ) {
  184. TimeoutTime = INFINITE;
  185. }
  186. ret = WaitForSingleObject(
  187. Resource->SharedSemaphore,
  188. TimeoutTime
  189. );
  190. if ( ret == WAIT_TIMEOUT ) {
  191. IF_DEBUG(RESOURCE) {
  192. DBGPRINTF(( DBG_CONTEXT,
  193. "%08p::[InetAcquireResourceShared] Sem timeout\n",
  194. Resource));
  195. }
  196. TimeoutCount++;
  197. if ( TimeoutCount == TIMEOUT_BREAK_COUNT ) {
  198. #if DBG && TIMEOUT_BREAK_COUNT > 0
  199. DebugBreak();
  200. #endif
  201. }
  202. IF_DEBUG(RESOURCE) {
  203. DBGPRINTF(( DBG_CONTEXT,
  204. "%08p::[InetAcquireResourceShared] Re-Waiting\n",
  205. Resource));
  206. }
  207. goto rewait;
  208. } else if ( ret != WAIT_OBJECT_0 ) {
  209. IF_DEBUG(RESOURCE) {
  210. DBGPRINTF(( DBG_CONTEXT,
  211. "%08p::[InetAcquireResourceShared] "
  212. "WaitForSingleObject Failed\n",
  213. Resource));
  214. }
  215. }
  216. }
  217. //
  218. // Now the resource is ours, for shared access
  219. //
  220. return TRUE;
  221. }
  222. BOOL
  223. InetAcquireResourceExclusive(
  224. IN PRTL_RESOURCE Resource,
  225. IN BOOL Wait
  226. )
  227. /*++
  228. Routine Description:
  229. The routine acquires the resource for exclusive access. Upon return from
  230. the procedure the resource is acquired for exclusive access.
  231. Arguments:
  232. Resource - Supplies the resource to acquire
  233. Wait - Indicates if the call is allowed to wait for the resource
  234. to become available for must return immediately
  235. Return Value:
  236. BOOL - TRUE if the resource is acquired and FALSE otherwise
  237. --*/
  238. {
  239. ULONG TimeoutCount = 0;
  240. DWORD TimeoutTime = INET_RES_TIMEOUT;
  241. DWORD ret;
  242. //
  243. // Loop until the resource is ours or exit if we cannot wait.
  244. //
  245. while (TRUE) {
  246. //
  247. // Enter the critical section
  248. //
  249. EnterCriticalSection(&Resource->CriticalSection);
  250. //
  251. // If there are no shared users and it is not currently acquired for
  252. // exclusive use then we can acquire the resource for exclusive
  253. // access. We also can acquire it if the resource indicates exclusive
  254. // access but there isn't currently an owner.
  255. //
  256. if ((Resource->NumberOfActive == 0)
  257. ||
  258. ((Resource->NumberOfActive == -1) &&
  259. (Resource->ExclusiveOwnerThread == NULL))) {
  260. //
  261. // The resource is ours, so indicate that we have it and
  262. // exit the critical section
  263. //
  264. Resource->NumberOfActive = -1;
  265. Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread;
  266. LeaveCriticalSection(&Resource->CriticalSection);
  267. return TRUE;
  268. }
  269. //
  270. // Otherwise check to see if we already have exclusive access to the
  271. // resource and can simply recusively acquire it again.
  272. //
  273. if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) {
  274. //
  275. // The resource is ours (recusively) so indicate that we have it
  276. // and exit the critial section
  277. //
  278. Resource->NumberOfActive -= 1;
  279. LeaveCriticalSection(&Resource->CriticalSection);
  280. return TRUE;
  281. }
  282. //
  283. // Check if we are allowed to wait or must return immedately, and
  284. // indicate that we didn't acquire the resource
  285. //
  286. if (!Wait) {
  287. LeaveCriticalSection(&Resource->CriticalSection);
  288. return FALSE;
  289. }
  290. //
  291. // Otherwise we need to wait to acquire the resource.
  292. // To wait we will increment the number of waiting exclusive,
  293. // release the lock, and wait on the exclusive semaphore
  294. //
  295. Resource->NumberOfWaitingExclusive += 1;
  296. LeaveCriticalSection(&Resource->CriticalSection);
  297. rewait:
  298. if ( Resource->Flags & RTL_RESOURCE_FLAG_LONG_TERM ) {
  299. TimeoutTime = INFINITE;
  300. }
  301. ret = WaitForSingleObject(
  302. Resource->ExclusiveSemaphore,
  303. TimeoutTime
  304. );
  305. if ( ret == WAIT_TIMEOUT ) {
  306. IF_DEBUG(RESOURCE) {
  307. DBGPRINTF(( DBG_CONTEXT,
  308. "%08p::[InetAcquireResourceExclusive] "
  309. "Sem Timeout\n",
  310. Resource));
  311. }
  312. TimeoutCount++;
  313. if ( TimeoutCount == TIMEOUT_BREAK_COUNT ) {
  314. #if DBG && TIMEOUT_BREAK_COUNT > 0
  315. DebugBreak();
  316. #endif
  317. }
  318. IF_DEBUG(RESOURCE) {
  319. DBGPRINTF(( DBG_CONTEXT,
  320. "%08p::[InetAcquireResourceExclusive] "
  321. "Re-Waiting\n",
  322. Resource));
  323. }
  324. goto rewait;
  325. } else if ( ret != WAIT_OBJECT_0 ) {
  326. IF_DEBUG(RESOURCE) {
  327. DBGPRINTF(( DBG_CONTEXT,
  328. "%08p::[InetAcquireResourceExclusive] "
  329. "WaitForSingleObject Failed\n",
  330. Resource));
  331. }
  332. }
  333. }
  334. return TRUE;
  335. }
  336. BOOL
  337. InetReleaseResource(
  338. IN PRTL_RESOURCE Resource
  339. )
  340. /*++
  341. Routine Description:
  342. This routine release the input resource. The resource can have been
  343. acquired for either shared or exclusive access.
  344. Arguments:
  345. Resource - Supplies the resource to release
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. LONG PreviousCount;
  351. BOOL fResult = FALSE;
  352. //
  353. // Enter the critical section
  354. //
  355. EnterCriticalSection(&Resource->CriticalSection);
  356. //
  357. // Test if the resource is acquired for shared or exclusive access
  358. //
  359. if (Resource->NumberOfActive > 0) {
  360. //
  361. // Releasing shared access to the resource, so decrement
  362. // the number of shared users
  363. //
  364. Resource->NumberOfActive -= 1;
  365. //
  366. // If the resource is now available and there is a waiting
  367. // exclusive user then give the resource to the waiting thread
  368. //
  369. if ((Resource->NumberOfActive == 0) &&
  370. (Resource->NumberOfWaitingExclusive > 0)) {
  371. //
  372. // Set the resource state to exclusive (but not owned),
  373. // decrement the number of waiting exclusive, and release
  374. // one exclusive waiter
  375. //
  376. Resource->NumberOfActive = -1;
  377. Resource->ExclusiveOwnerThread = NULL;
  378. Resource->NumberOfWaitingExclusive -= 1;
  379. if ( !ReleaseSemaphore(
  380. Resource->ExclusiveSemaphore,
  381. 1,
  382. &PreviousCount
  383. )) {
  384. goto cleanup;
  385. }
  386. }
  387. } else if (Resource->NumberOfActive < 0) {
  388. //
  389. // Releasing exclusive access to the resource, so increment the
  390. // number of active by one. And continue testing only
  391. // if the resource is now available.
  392. //
  393. Resource->NumberOfActive += 1;
  394. if (Resource->NumberOfActive == 0) {
  395. //
  396. // The resource is now available. Remove ourselves as the
  397. // owner thread
  398. //
  399. Resource->ExclusiveOwnerThread = NULL;
  400. //
  401. // If there is another waiting exclusive then give the resource
  402. // to it.
  403. //
  404. if (Resource->NumberOfWaitingExclusive > 0) {
  405. //
  406. // Set the resource to exclusive, and its owner undefined.
  407. // Decrement the number of waiting exclusive and release one
  408. // exclusive waiter
  409. //
  410. Resource->NumberOfActive = -1;
  411. Resource->NumberOfWaitingExclusive -= 1;
  412. if ( !ReleaseSemaphore(
  413. Resource->ExclusiveSemaphore,
  414. 1,
  415. &PreviousCount
  416. )) {
  417. goto cleanup;
  418. }
  419. //
  420. // Check to see if there are waiting shared, who should now get
  421. // the resource
  422. //
  423. } else if (Resource->NumberOfWaitingShared > 0) {
  424. //
  425. // Set the new state to indicate that all of the shared
  426. // requesters have access and there are no more waiting
  427. // shared requesters, and then release all of the shared
  428. // requsters
  429. //
  430. Resource->NumberOfActive = Resource->NumberOfWaitingShared;
  431. Resource->NumberOfWaitingShared = 0;
  432. if ( !ReleaseSemaphore(
  433. Resource->SharedSemaphore,
  434. Resource->NumberOfActive,
  435. &PreviousCount
  436. )) {
  437. goto cleanup;
  438. }
  439. }
  440. }
  441. #if DBG
  442. } else {
  443. //
  444. // The resource isn't current acquired, there is nothing to release
  445. // so tell the user the mistake
  446. //
  447. DBGPRINTF(( DBG_CONTEXT,
  448. "%08p::[InetReleaseResource] "
  449. "Resource released too many times!\n",
  450. Resource));
  451. DebugBreak();
  452. #endif
  453. }
  454. //
  455. // If we reached here, we successfully released the resource
  456. //
  457. fResult = TRUE;
  458. cleanup:
  459. //
  460. // Exit the critical section, and return to the caller
  461. //
  462. LeaveCriticalSection(&Resource->CriticalSection);
  463. return fResult;
  464. }
  465. BOOL
  466. InetConvertSharedToExclusive(
  467. IN PRTL_RESOURCE Resource
  468. )
  469. /*++
  470. Routine Description:
  471. This routine converts a resource acquired for shared access into
  472. one acquired for exclusive access. Upon return from the procedure
  473. the resource is acquired for exclusive access
  474. Arguments:
  475. Resource - Supplies the resource to acquire for shared access, it
  476. must already be acquired for shared access
  477. Return Value:
  478. None
  479. --*/
  480. {
  481. DWORD ret;
  482. DWORD TimeoutTime = INET_RES_TIMEOUT;
  483. ULONG TimeoutCount = 0;
  484. //
  485. // Enter the critical section
  486. //
  487. EnterCriticalSection(&Resource->CriticalSection);
  488. //
  489. // If there is only one shared user (it's us) and we can acquire the
  490. // resource for exclusive access.
  491. //
  492. if (Resource->NumberOfActive == 1) {
  493. //
  494. // The resource is ours, so indicate that we have it and
  495. // exit the critical section, and return
  496. //
  497. Resource->NumberOfActive = -1;
  498. Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread;
  499. LeaveCriticalSection(&Resource->CriticalSection);
  500. return TRUE;
  501. }
  502. //
  503. // If the resource is currently acquired exclusive and it's us then
  504. // we already have exclusive access
  505. //
  506. if ((Resource->NumberOfActive < 0) &&
  507. (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread)) {
  508. //
  509. // We already have exclusive access to the resource so we'll just
  510. // exit the critical section and return
  511. //
  512. LeaveCriticalSection(&Resource->CriticalSection);
  513. return TRUE;
  514. }
  515. //
  516. // If the resource is acquired by more than one shared then we need
  517. // to wait to get exclusive access to the resource
  518. //
  519. if (Resource->NumberOfActive > 1) {
  520. //
  521. // To wait we will decrement the fact that we have the resource for
  522. // shared, and then loop waiting on the exclusive lock, and then
  523. // testing to see if we can get exclusive access to the resource
  524. //
  525. Resource->NumberOfActive -= 1;
  526. while (TRUE) {
  527. //
  528. // Increment the number of waiting exclusive, exit and critical
  529. // section and wait on the exclusive semaphore
  530. //
  531. Resource->NumberOfWaitingExclusive += 1;
  532. LeaveCriticalSection(&Resource->CriticalSection);
  533. rewait:
  534. if ( Resource->Flags & RTL_RESOURCE_FLAG_LONG_TERM ) {
  535. TimeoutTime = INFINITE;
  536. }
  537. ret = WaitForSingleObject(
  538. Resource->ExclusiveSemaphore,
  539. TimeoutTime
  540. );
  541. if ( ret == WAIT_TIMEOUT ) {
  542. IF_DEBUG(RESOURCE) {
  543. DBGPRINTF(( DBG_CONTEXT,
  544. "%08p::[InetConvertSharedToExclusive] Sem timeout\n",
  545. Resource));
  546. }
  547. TimeoutCount++;
  548. if ( TimeoutCount == TIMEOUT_BREAK_COUNT ) {
  549. #if DBG && TIMEOUT_BREAK_COUNT > 0
  550. DebugBreak();
  551. #endif
  552. }
  553. IF_DEBUG(RESOURCE) {
  554. DBGPRINTF(( DBG_CONTEXT,
  555. "%08p::[InetConvertSharedToExclusive] Re-Waiting\n",
  556. Resource));
  557. }
  558. goto rewait;
  559. } else if ( ret != WAIT_OBJECT_0 ) {
  560. IF_DEBUG(RESOURCE) {
  561. DBGPRINTF(( DBG_CONTEXT,
  562. "%08p::[InetConvertSharedToExclusive] "
  563. "WaitForSingleObject Failed\n",
  564. Resource));
  565. }
  566. return FALSE;
  567. }
  568. //
  569. // Enter the critical section
  570. //
  571. EnterCriticalSection(&Resource->CriticalSection);
  572. //
  573. // If there are no shared users and it is not currently acquired
  574. // for exclusive use then we can acquire the resource for
  575. // exclusive access. We can also acquire it if the resource
  576. // indicates exclusive access but there isn't currently an owner
  577. //
  578. if ((Resource->NumberOfActive == 0)
  579. ||
  580. ((Resource->NumberOfActive == -1) &&
  581. (Resource->ExclusiveOwnerThread == NULL))) {
  582. //
  583. // The resource is ours, so indicate that we have it and
  584. // exit the critical section and return.
  585. //
  586. Resource->NumberOfActive = -1;
  587. Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread;
  588. LeaveCriticalSection(&Resource->CriticalSection);
  589. return TRUE;
  590. }
  591. //
  592. // Otherwise check to see if we already have exclusive access to
  593. // the resource and can simply recusively acquire it again.
  594. //
  595. if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) {
  596. //
  597. // The resource is ours (recusively) so indicate that we have
  598. // it and exit the critical section and return.
  599. //
  600. Resource->NumberOfActive -= 1;
  601. LeaveCriticalSection(&Resource->CriticalSection);
  602. return TRUE;
  603. }
  604. }
  605. }
  606. //
  607. // The resource is not currently acquired for shared so this is a
  608. // spurious call
  609. //
  610. #if DBG
  611. DBGPRINTF(( DBG_CONTEXT,
  612. "%08p::[InetConvertSharedToExclusive] "
  613. "Failed error - SHARED_RESOURCE_CONV_ERROR\n",
  614. Resource));
  615. DebugBreak();
  616. #endif
  617. return FALSE;
  618. }
  619. BOOL
  620. InetConvertExclusiveToShared(
  621. IN PRTL_RESOURCE Resource
  622. )
  623. /*++
  624. Routine Description:
  625. This routine converts a resource acquired for exclusive access into
  626. one acquired for shared access. Upon return from the procedure
  627. the resource is acquired for shared access
  628. Arguments:
  629. Resource - Supplies the resource to acquire for shared access, it
  630. must already be acquired for exclusive access
  631. Return Value:
  632. None
  633. --*/
  634. {
  635. LONG PreviousCount;
  636. //
  637. // Enter the critical section
  638. //
  639. EnterCriticalSection(&Resource->CriticalSection);
  640. //
  641. // If there is only one shared user (it's us) and we can acquire the
  642. // resource for exclusive access.
  643. //
  644. if (Resource->NumberOfActive == -1) {
  645. Resource->ExclusiveOwnerThread = NULL;
  646. //
  647. // Check to see if there are waiting shared, who should now get the
  648. // resource along with us
  649. //
  650. if (Resource->NumberOfWaitingShared > 0) {
  651. //
  652. // Set the new state to indicate that all of the shared requesters
  653. // have access including us, and there are no more waiting shared
  654. // requesters, and then release all of the shared requsters
  655. //
  656. Resource->NumberOfActive = Resource->NumberOfWaitingShared + 1;
  657. Resource->NumberOfWaitingShared = 0;
  658. if ( !ReleaseSemaphore(
  659. Resource->SharedSemaphore,
  660. Resource->NumberOfActive - 1,
  661. &PreviousCount
  662. )) {
  663. LeaveCriticalSection(&Resource->CriticalSection);
  664. return FALSE;
  665. }
  666. } else {
  667. //
  668. // There is no one waiting for shared access so it's only ours
  669. //
  670. Resource->NumberOfActive = 1;
  671. }
  672. LeaveCriticalSection(&Resource->CriticalSection);
  673. return TRUE;
  674. }
  675. //
  676. // The resource is not currently acquired for exclusive, or we've
  677. // recursively acquired it, so this must be a spurious call
  678. //
  679. #if DBG
  680. DBGPRINTF(( DBG_CONTEXT,
  681. "%08p::[InetConvertExclusiveToShared] "
  682. "Failed error - SHARED_RESOURCE_CONV_ERROR\n",
  683. Resource));
  684. DebugBreak();
  685. #endif
  686. return FALSE;
  687. }
  688. VOID
  689. InetDeleteResource (
  690. IN PRTL_RESOURCE Resource
  691. )
  692. /*++
  693. Routine Description:
  694. This routine deletes (i.e., uninitializes) the input resource variable
  695. Arguments:
  696. Resource - Supplies the resource variable being deleted
  697. Return Value:
  698. None
  699. --*/
  700. {
  701. DeleteCriticalSection( &Resource->CriticalSection );
  702. CloseHandle(Resource->SharedSemaphore);
  703. CloseHandle(Resource->ExclusiveSemaphore);
  704. ZeroMemory( Resource, sizeof( *Resource ) );
  705. #if DBG
  706. InterlockedIncrement( &g_InetResourcesDeleted );
  707. #endif
  708. return;
  709. }
  710. VOID
  711. InetDumpResource(
  712. IN PRTL_RESOURCE Resource
  713. )
  714. {
  715. DBGPRINTF(( DBG_CONTEXT, "Resource @ %p\n",
  716. Resource));
  717. DBGPRINTF(( DBG_CONTEXT, " NumberOfWaitingShared = %lx\n",
  718. Resource->NumberOfWaitingShared));
  719. DBGPRINTF(( DBG_CONTEXT, " NumberOfWaitingExclusive = %lx\n",
  720. Resource->NumberOfWaitingExclusive));
  721. DBGPRINTF(( DBG_CONTEXT, " NumberOfActive = %lx\n",
  722. Resource->NumberOfActive));
  723. return;
  724. }